diff --git a/FL/About_Dialog.fl b/FL/About_Dialog.fl deleted file mode 100644 index 2504854..0000000 --- a/FL/About_Dialog.fl +++ /dev/null @@ -1,100 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -Function {open_url( const char *url )} {open return_type void -} { - code {fl_open_uri( url );} {} -} - -class About_Dialog {open -} { - Function {About_Dialog( const char *logo_filename )} {open - } { - code {make_window( logo_filename );} {} - } - Function {run()} {open return_type void - } { - code {window->show(); - -while ( window->shown() ) - Fl::wait(); - -delete window;} {} - } - Function {make_window( const char *logo_filename )} {open private - } { - Fl_Window window { - label About - callback {o->hide(); - -if ( logo_box->image() ) -{ - ((Fl_Shared_Image*)logo_box->image())->release(); - logo_box->image( 0 ); -}} open selected - private xywh {879 215 560 695} type Double - visible - } { - Fl_Tabs {} {open - xywh {0 352 558 296} - } { - Fl_Group {} { - label Credits open - xywh {2 386 553 261} - } { - Fl_Box credits { - label {} - xywh {5 389 545 249} box ROUNDED_BOX color 46 labelsize 18 - } - } - Fl_Group {} { - label License open - xywh {2 378 553 268} hide - } { - Fl_Box copyright { - label COPYRIGHT - xywh {43 389 462 22} labeltype SHADOW_LABEL labelfont 1 labelsize 18 - } - Fl_Box {} { - label {This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.} - xywh {10 414 535 225} box ROUNDED_BOX color 46 labelfont 1 labelsize 12 labelcolor 53 align 144 - } - } - } - Fl_Box logo_box { - label VERSION - xywh {5 5 550 305} color 48 labelfont 1 labelsize 18 align 16 - code0 {o->image( Fl_Shared_Image::get( logo_filename ) );} - code1 {o->label( VERSION );} - } - Fl_Return_Button {} { - label Rock - callback {o->window()->do_callback();} - xywh {400 660 76 30} - } - Fl_Button website_url { - label {http://non-daw.tuxfamily.org} - callback {open_url( o->label() );} - xywh {125 660 245 30} color 14 labeltype SHADOW_LABEL labelcolor 6 - } - Fl_Box title { - label TITLE - xywh {5 317 545 29} labeltype SHADOW_LABEL labelfont 3 labelsize 17 - } - } - } -} diff --git a/FL/Fl_Blink_Button.H b/FL/Fl_Blink_Button.H deleted file mode 100644 index bc81303..0000000 --- a/FL/Fl_Blink_Button.H +++ /dev/null @@ -1,162 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include - -/* Kind of like Fl_Light_Button except that the whole thing is the - * indicator and it can optionally blink */ - -class Fl_Blink_Button : public Fl_Button -{ - bool _on; - int _blink_interval; - bool _blinking; - bool _ignore_input; - - static void - update_cb ( void *v ) - { - ((Fl_Blink_Button*)v)->update_cb(); - } - - - float - blink_interval_as_fraction_of_seceond ( void ) const - { - return (float)_blink_interval / 1000; - } - - void - update_cb ( void ) - { - Fl::repeat_timeout( blink_interval_as_fraction_of_seceond(), update_cb, this ); - - _on = ! _on; - - redraw(); - } - -public: - - enum - { - SLOW=500, - MEDIUM=300, - FAST=100, - DEFAULT=500 - }; - - Fl_Blink_Button ( int X, int Y, int W, int H, const char *L=0 ) - : Fl_Button( X, Y, W, H, L ) - { - _blinking = true; - _on = false; - _ignore_input = false; - _blink_interval = DEFAULT; - - type( FL_TOGGLE_BUTTON ); - } - - virtual - ~Fl_Blink_Button () - { - if ( value() ) - Fl::remove_timeout( update_cb, this ); - } - - void ignore_input ( bool b ) - { - _ignore_input = b; - } - - bool ignore_input ( void ) const - { - return _ignore_input; - } - - void blink ( bool b ) - { - _blinking = b; - if ( ! b ) - _on = true; - } - - bool blink ( void ) const - { - return _blinking; - } - - void - blink_interval ( float v ) - { - _blink_interval = v * 1000; - if ( value() ) - { - Fl::remove_timeout( update_cb, this ); - Fl::add_timeout( blink_interval_as_fraction_of_seceond(), update_cb, this ); - } - } - - virtual void value ( float v ) - { - bool b = v; - - if ( b != value() ) - { - if ( b ) - { - if ( _blinking ) - { - /* just to be safe.. */ - Fl::remove_timeout( update_cb, this ); - Fl::add_timeout( blink_interval_as_fraction_of_seceond(), update_cb, this ); - } - Fl_Button::value( b ); - redraw(); - } - else - { - Fl_Button::value( b ); - Fl::remove_timeout( update_cb, this ); - redraw(); - } - } - } - - virtual float value ( void ) { return (bool)Fl_Button::value(); } - - virtual void - draw ( void ) - { - draw_box( value() ? box() : down_box(), x(), y(), w(), h(), - ( value() != 0 && _on ) ? selection_color() : color() ); - draw_label(); - } - - virtual int handle ( int m ) - { - if ( _ignore_input ) - return 0; - else - return Fl_Button::handle( m ); - } -}; diff --git a/FL/Fl_DialX.C b/FL/Fl_DialX.C deleted file mode 100644 index 64973b5..0000000 --- a/FL/Fl_DialX.C +++ /dev/null @@ -1,124 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Fl_DialX.H" -#include -#include - -void -Fl_DialX::draw ( void ) -{ - int X,Y,S; - int act = active_r(); - - { - int ox, oy, ww, hh, side; - ox = x(); - oy = y(); - ww = w(); - hh = h(); - - if (ww > hh) - { - side = hh; - ox = ox + (ww - side) / 2; - } - else - { - side = ww; - oy = oy + (hh - side) / 2; - } - side = w() > h() ? hh : ww; - - X = ox; - Y = oy; - S = side; - } - - draw_box(); - draw_label(); - - double angle = ( angle2() - angle1() ) * ( value() - minimum()) / ( maximum() - minimum() ) + angle1(); - - fl_draw_box( box(), X, Y, S, S, color() ); - - /* shrink a bit */ - int OX = x(); - int OY = y(); - X += S / 8; - Y += S / 8; - int OS = S; - S -= S / 4; - - fl_line_style( FL_SOLID, S / 12 ); - - /* background arc */ - - Fl_Color c = fl_darker( color() ); - if ( !act ) - c = fl_inactive( c ); - - fl_color( c ); - fl_arc( X, Y, S, S, 270 - angle1(), 270 - angle2() ); - - /* foreground arc */ - c = selection_color(); - - if ( !act ) - c = fl_inactive( c ); - - fl_color(c); - fl_arc( X, Y, S, S, 270 - angle1(), 270 - angle ); - - fl_line_style( FL_SOLID, 0 ); - - if ( act ) - { - int W = OS; - int H = OS; - - fl_push_matrix(); - fl_translate(OX+W/2, OY+H/2); - fl_scale(W, H); - fl_rotate(310+angle); - fl_color( fl_color_add_alpha( FL_WHITE, 127 )); - fl_begin_polygon(); fl_circle(-0.26, 0.26, 0.12); fl_end_polygon(); - fl_color( FL_WHITE ); - fl_begin_polygon(); fl_circle(-0.26, 0.26, 0.06); fl_end_polygon(); - - fl_pop_matrix(); - } - - fl_color( fl_contrast( labelcolor(), color() ) ); - - if ( Fl::belowmouse() == this ) - { - char s[128]; - - fl_font( FL_HELVETICA, 9 ); - - char buf[128]; - format(buf); - - snprintf( s, sizeof( s ), buf, value() ); - - fl_color( FL_FOREGROUND_COLOR ); - fl_draw( s, X, Y, S, S, FL_ALIGN_CENTER ); - } -} diff --git a/FL/Fl_DialX.H b/FL/Fl_DialX.H deleted file mode 100644 index d27da3c..0000000 --- a/FL/Fl_DialX.H +++ /dev/null @@ -1,36 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -class Fl_DialX : public Fl_Dial -{ - -public: - - Fl_DialX ( int X, int Y, int W, int H, const char *L=0 ) : Fl_Dial(X,Y,W,H,L) - { - } - - virtual void draw ( void ); - virtual ~Fl_DialX() { } -}; - diff --git a/FL/Fl_Flip_Button.H b/FL/Fl_Flip_Button.H deleted file mode 100644 index d3e0b1e..0000000 --- a/FL/Fl_Flip_Button.H +++ /dev/null @@ -1,72 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Simple extension of Fl_Button to support different lables for the - * two button states. Simpler than using a an Fl_Choice when all you - * need is two states. Set the label to "foo/bar" for "foo" to be the - * off label and "bar" the on. Obviously you should make sure that - * each label will fit. */ - -#pragma once - -#include - -#include -#include - -class Fl_Flip_Button : public Fl_Button -{ - - char *_off; - char *_on; - -public: - - Fl_Flip_Button ( int X, int Y, int W, int H, const char *L = 0 ) : - Fl_Button( X, Y, W, H, 0 ) - { - sscanf( L, "%m[^/]/%ms", &_off, &_on ); - - type( FL_TOGGLE_BUTTON ); - } - - virtual ~Fl_Flip_Button ( ) - { - if ( _off ) free( _off ); - if ( _on ) free( _on ); - } - -protected: - - virtual void - draw ( void ) - { - if ( value() ) - { - if ( label() != _on ) - label( _on ); - } - else - if ( label() != _off ) - label( _off ); - - draw_box( box(), x(), y(), w(), h(), value() ? selection_color() : color() ); - draw_label(); - } -}; diff --git a/FL/Fl_Flowpack.H b/FL/Fl_Flowpack.H deleted file mode 100644 index cdb3779..0000000 --- a/FL/Fl_Flowpack.H +++ /dev/null @@ -1,237 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include - -class Fl_Flowpack : public Fl_Group -{ - int _hspacing; - int _vspacing; - bool _flow; - bool _flowdown; - int _initial_height; - int _initial_width; - -public: - - Fl_Flowpack ( int X, int Y, int W, int H, const char *L = 0 ) - : Fl_Group( X, Y, W, H, L ) - { - resizable( 0 ); - _hspacing = _vspacing = 0; - _initial_width = W; - _initial_height = H; - _flow = true; - _flowdown = false; - } - - virtual ~Fl_Flowpack ( ) - { - } - - - void vspacing ( int v ) { _vspacing = v; } - int vspacing ( void ) const { return _vspacing; }; - - void hspacing ( int h ) { _hspacing = h; } - int hspacing ( void ) const { return _hspacing; }; - - bool flow ( void ) const { return _flow; } - void flow ( bool v ) { _flow = v; } - - bool flowdown ( void ) const { return _flowdown; } - void flowdown ( bool v ) { _flowdown = v; } - - void - add ( Fl_Widget *w ) - { - Fl_Group::add( w ); - dolayout(); - } - - void - remove ( Fl_Widget *w ) - { - Fl_Group::remove( w ); - dolayout(); - } - - void - resize ( int X, int Y, int W, int H ) - { - _initial_width = W; - _initial_height = H; - - layout(); - - Fl_Group::resize( X, Y, w(), h() ); - } - - void - draw ( void ) - { - layout(); - Fl_Group::draw(); - } - - void dolayout ( void ) - { - layout(); - } - - void - layout ( void ) - { - resizable( 0 ); - - int W; - int H; - int X = 0; - int Y = 0; - int LW = 0; - int LH = 0; - int LX = 0; - int LY = 0; - int RH = 0; -// int RY = 0; - int CW = 0; - - if ( _flow ) - { - H = 0; - W = 0; - } - else - { - H = _initial_height; - W = _initial_width; - } - - for ( int i = 0; i < children(); ++i ) - { - Fl_Widget *o = child( i ); - - if ( ! o->visible() ) - continue; - - if ( _flow ) - { - if ( _flowdown ) - { - if ( Y + o->h() <= _initial_height ) - { - /* if it'll fit in this column, put it below the previous widget */ - X = LX; - } - else - { - Y = H; - CW = 0; - } - - CW = o->w() > CW ? o->w() : CW; - RH = Y + o->h() > RH ? Y + o->h() : RH; - } - else - { - if ( X + o->w() >= _initial_width ) - { - /* maybe wrap to the next row */ - H += RH + _vspacing; -// RY = Y; - RH = 0; - if ( X > W ) - W = X; - - X = 0; - } - else - { - /* otherwise, put it in the next column */ - Y = H; - - } - - RH = o->h() > RH ? o->h() : RH; - - } - } - - LW = o->w(); - LH = o->h(); - - LX = X; - LY = Y; - - if ( _flow ) - { - if ( _flowdown ) - { - Y += LH + _vspacing; - X += CW + _hspacing; - } - else - { - Y += RH + _vspacing; - X += LW + _hspacing; - } - } - else - { - if ( type() == Fl_Pack::HORIZONTAL ) - { - X += LW + _hspacing; - LH = _initial_height; - W = X; - } - else - { - Y += LH + _vspacing; - LW = _initial_width; - H = Y; - } - } - - - if ( ! ( o->x() == x() + LX && - o->y() == y() + LY && - o->w() == LW && - o->h() == LH ) ) - o->resize( x() + LX, - y() + LY, - LW, - LH); - } - - if ( _flow ) - { - H += RH; - if ( X > W ) - W = X; - - /* if ( _flowdown ) */ - /* H = _initial_height; */ - } - - Fl_Group::resize( x(), y(), W, H ); - } -}; diff --git a/FL/Fl_Labelpad_Group.H b/FL/Fl_Labelpad_Group.H deleted file mode 100644 index bf7e641..0000000 --- a/FL/Fl_Labelpad_Group.H +++ /dev/null @@ -1,78 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* wrap a widget in a group as wide as the widget's label. This is - * useful when you want to put labeled widgets into a pack */ - -#include -#include -#include - -class Fl_Labelpad_Group : public Fl_Group -{ -public: - - static void measure_label ( Fl_Widget *o, int &W, int &H ) - { - W = fl_width( o->label() ); - H = fl_height(); - } - - Fl_Labelpad_Group ( Fl_Widget *o ) : Fl_Group( 0, 0, 50, 50, 0 ) - { - resizable( 0 ); - - end(); - - add( o ); - - fl_font( o->labelfont(), o->labelsize() ); - - int W, H; - - measure_label( o, W, H ); - - // set size to contain widget - if ( o->align() & ( FL_ALIGN_TOP | FL_ALIGN_BOTTOM ) ) - size( W > o->w() ? W : o->w(), o->h() + H ); - if ( o->align() & ( FL_ALIGN_LEFT | FL_ALIGN_RIGHT ) ) - size( o->w() + W, H > o->h() ? H : o->h() ); - - // center widget in group - if ( o->align() & FL_ALIGN_TOP ) - o->position( x() + w() / 2 - (o->w() / 2 ), y() + H ); - else if ( o->align() & FL_ALIGN_BOTTOM ) - o->position( x() + w() / 2 - (o->w() / 2 ), y() ); - else if ( o->align() & FL_ALIGN_RIGHT ) - o->position( x(), y() ); - else if ( o->align() & FL_ALIGN_LEFT ) - o->position( x() + W, y() ); - else - { - /* TODO: other alignments */ - } - - resizable(o); - init_sizes(); - } - - virtual ~Fl_Labelpad_Group ( ) - { - } -}; diff --git a/FL/Fl_Menu_Settings.C b/FL/Fl_Menu_Settings.C deleted file mode 100644 index a2f513e..0000000 --- a/FL/Fl_Menu_Settings.C +++ /dev/null @@ -1,338 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Fl_Menu_Settings.H" - -#include - -/* code to dump and restore (portions of) an Fl_Menu_ */ - -#define MAX_PATH 1024 - -void -Fl_Menu_Settings::remove_ampersands ( char *str, int n ) -{ - char *d = str; - char *s = str; - - while ( n-- ) - { - if ( *s == '&' ) - { - ++s; - continue; - } - - *(d++) = *(s++); - } - - *d = '\0'; -} - -void -Fl_Menu_Settings::indent ( FILE *fp, int n ) -{ - while ( n-- ) - fprintf( fp, "\t" ); -} - -int -Fl_Menu_Settings::item_pathname_x ( char *path, int n, const Fl_Menu_Item *item ) -{ - int r = Fl_Menu_::item_pathname( path, n, item ); - - remove_ampersands( path, n ); - - return r; -} - -/** dump options from submenu /menu/ of menubar /bar/ to file /fp/ */ -const Fl_Menu_Item * -Fl_Menu_Settings::dump ( Fl_Menu_ *bar, const Fl_Menu_Item *menu, FILE *fp, int depth ) -{ - static char path[256]; - const Fl_Menu_Item *m = menu; - - for ( ; m->text; ++m ) - { - bool is_radio = false; - - if ( m->flags & FL_SUBMENU ) -// if ( m->submenu() ) - { - strcpy( path, m->text ); - remove_ampersands( path, strlen( path ) ); - - indent( fp, depth ); - fprintf( fp, "%s\n", path ); - - /* recurse */ - m = dump( bar, ++m, fp, depth + 1 ); - -// ++m; - -// m = dump( bar, m->flags & FL_SUBMENU_POINTER ? (Fl_Menu_Item*) m->user_data() : m, fp, depth + 1 ); - - if ( ! depth ) - break; - else - continue; - } - - if ( m->radio() ) - is_radio = true; - -// bar->item_pathname( path, sizeof( path ) - 1, m ); - item_pathname_x( path, sizeof( path ) - 1, m ); - - - if ( m->flags & FL_MENU_TOGGLE || m->flags & FL_MENU_RADIO ) - { - if ( ! is_radio ) - { - indent( fp, depth ); - - fprintf( fp, "%s\n", rindex( path, '/' ) + 1 ); - - indent( fp, depth + 1 ); - - fprintf( fp, "%s\n", m->flags & FL_MENU_VALUE ? "true" : "false" ); - } - else if ( m->flags & FL_MENU_VALUE ) - { - *rindex( path, '/' ) = '\0'; - - indent( fp, depth ); - - fprintf( fp, "%s\n", path + strlen( path ) + 1 ); - } - } - - } - - return m; -} - -/** dump menu to file /name/ starting at /item. */ -int -Fl_Menu_Settings::dump ( const Fl_Menu_Item *item, const char *name ) -{ - FILE *fp = fopen( name, "w" ); - - if ( ! fp ) - return false; - - dump( this, item, fp, 0 ); - - fclose( fp ); - - - return true; -} - -#define strlcat strncat - -/* taken from Fl_Menu_.cxx and modified to ignore hotkeys and case */ -const Fl_Menu_Item * -Fl_Menu_Settings::find_item_x ( const char *name, const Fl_Menu_Item *item ) -{ - char menupath [ MAX_PATH ] = ""; // File/Export - - const Fl_Menu_Item *m = item ? item : menu(); - - int depth = 0; - - while ( depth >= 0 ) - for ( ;m ; ++m ) - { - if ( m->flags & FL_SUBMENU ) - { - // IT'S A SUBMENU - // we do not support searches through FL_SUBMENU_POINTER links - if ( menupath[0] ) - strlcat( menupath, "/", sizeof( menupath ) ); - - strlcat( menupath, m->label(), sizeof( menupath ) ); - - remove_ampersands( menupath, strlen( menupath ) ); - - if ( ! strcasecmp( menupath, name ) ) - return m; - else - { - ++depth; - continue; - } - } - else - { - if ( ! m->label() ) - { - // END OF SUBMENU? Pop back one level. - char *ss = strrchr( menupath, '/' ); - if ( ss ) - *ss = 0; - else - menupath[0] = '\0'; - - --depth; - ++m; - - break; - } - - // IT'S A MENU ITEM - char itempath[ MAX_PATH ]; // eg. Edit/Copy - strcpy( itempath, menupath ); - - if ( itempath[0] ) - strlcat( itempath, "/", sizeof( itempath ) ); - - strlcat( itempath, m->label(), sizeof( itempath ) ); - - remove_ampersands( itempath, strlen( itempath ) ); - - if ( !strcasecmp( itempath, name ) ) - return m; - } - } - - return ( Fl_Menu_Item * )0; -} - - -static void -path_push ( char *path, const char *s ) -{ - strcat( path, s ); - strcat( path, "/" ); -} - -static void -path_pop ( char *path ) -{ - char *s; - - int l = strlen( path ); - - if ( ! l ) - return; - - if ( path[ l - 1 ] == '/' ) - path[ l - 1 ] = '\0'; - - s = rindex( path, '/' ); - - if ( s ) - *(s + 1) = '\0'; - else - *path = '\0'; -} - -void -Fl_Menu_Settings::load ( Fl_Menu_ *bar, const Fl_Menu_Item *item, FILE *fp, int depth, char *path, int pmax ) -{ - char line[256]; - - while ( ! feof( fp ) ) - { - *line = '\0'; - - fgets( line, sizeof( line ), fp ); - - if ( *line == '#' ) - continue; - - line[ strlen( line ) - 1 ] = '\0'; - - int ld = strspn( line, "\t" ); - - if ( ld > depth ) - { - path_push( path, line + ld ); - - ++depth; - -// load( bar, item, fp, depth + 1, path, pmax ); - /* */; - } - else if ( ld < depth ) - { - /* we should know the path and the value now */ - - // path_pop( path ); - *rindex( path, '/' ) = '\0'; - -// printf( "%s = %s\n", path, path + strlen( path ) + 1 ); - - const Fl_Menu_Item *it = find_item_x( path, item + 1 ); - - if ( it && it->radio() ) /* radio button */ - { - bar->picked( it ); - - path_pop( path ); - } - else /* toggle */ - { - *rindex( path, '/' ) = '\0'; - - if ( ( it = find_item_x( path, item + 1 ) ) && it->checkbox() ) - { - int v = 0 == strcasecmp( "true", (path + strlen( path ) + 1 ) ); - - if ( v != ( it->value() != 0 ) /* grr, FLTK */ ) - bar->picked( it ); - } - - } - - while ( ld < depth ) - { - path_pop( path ); - depth--; - } - - path_push( path, line + ld ); - } - else /* d == depth */ - { - /* doesn't apply? */ - } - } -} - -/** load settings from file /name/ into menu starting at /item */ -int -Fl_Menu_Settings::load ( const Fl_Menu_Item *item, const char *name ) -{ - FILE *fp = fopen( name, "r" ); - - if ( ! fp ) - return false; - - char path[ MAX_PATH ]; - path[0] = '\0'; - - load( this, item, fp, 0, path, sizeof( path ) ); - - fclose( fp ); - - return true; -} diff --git a/FL/Fl_Menu_Settings.H b/FL/Fl_Menu_Settings.H deleted file mode 100644 index 7a94697..0000000 --- a/FL/Fl_Menu_Settings.H +++ /dev/null @@ -1,43 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - - -#include -#include - -class Fl_Menu_Settings : public Fl_Menu_ -{ - - void remove_ampersands ( char *str, int n ); - void indent ( FILE *fp, int n ); - const Fl_Menu_Item * dump ( Fl_Menu_ *bar, const Fl_Menu_Item *menu, FILE *fp, int depth ); - void load ( Fl_Menu_ *bar, const Fl_Menu_Item *item, FILE *fp, int depth, char *path, int pmax ); - -public: - - - int item_pathname_x ( char *path, int n, const Fl_Menu_Item *item ); - const Fl_Menu_Item * find_item_x ( const char *name, const Fl_Menu_Item *item ); - - int dump ( const Fl_Menu_Item *item, const char *name ); - int load ( const Fl_Menu_Item *item, const char *name ); - - -}; diff --git a/FL/Fl_Packscroller.H b/FL/Fl_Packscroller.H deleted file mode 100644 index 0661b48..0000000 --- a/FL/Fl_Packscroller.H +++ /dev/null @@ -1,212 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2010 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Scrolling group suitable for containing a single child (a - * pack). When the Fl_Packscroller is resized, the child will be resized - * too. No scrollbars are displayed, but the widget responds to - * FL_MOUSEWHEEL events. */ - -#pragma once - -#include -#include -#include - -/* FIXME: Optimize scroll */ - -class Fl_Packscroller : public Fl_Group -{ - int _increment; - int _yposition; - static const int sbh = 15; /* scroll button height */ - -public: - - Fl_Packscroller ( int X, int Y, int W, int H, const char *L = 0 ) : Fl_Group( X, Y, W, H, L ) - { - _increment = 30; - _yposition = 0; -// color( FL_WHITE ); - } - - int increment ( void ) const { return _increment; } - void increment ( int v ) { _increment = v; } - - void yposition ( int v ) - { - if ( ! children() ) - return; - - int Y = v; - - if ( Y > 0 ) - Y = 0; - - const int H = h(); -// - (sbh * 2); - - Fl_Widget *o = child( 0 ); - - if ( o->h() > H && - Y + o->h() < H ) - Y = H - o->h(); - else if ( o->h() < H ) - Y = 0; - - if ( _yposition != Y ) - { - _yposition = Y; - - damage( FL_DAMAGE_SCROLL ); - } - } - - int yposition ( void ) const - { - if ( children() ) - return child( 0 )->y() - (y() + sbh); - - return 0; - } - - void bbox ( int &X, int &Y, int &W, int &H ) - { - X = x(); - Y = y() + ( sbh * top_sb_visible() ); - W = w(); - H = h() - ( sbh * ( top_sb_visible() + bottom_sb_visible() ) ); - } - - int top_sb_visible ( void ) - { - return children() && child(0)->y() != y() ? 1 : 0; - } - - int bottom_sb_visible ( void ) - { - if ( children() ) - { - Fl_Widget *o = child( 0 ); - - if ( o->h() > h() && o->y() + o->h() != y() + h() ) - return 1; - } - - return 0; - } - - virtual void - draw ( void ) - { - if ( damage() & FL_DAMAGE_ALL ) - { - fl_rectf( x(), y(), w(), h(), color() ); - } - - if ( ! children() ) - return; - - Fl_Widget *o = child( 0 ); - - o->position( x(), y() + _yposition ); - - const int top_sb = top_sb_visible(); - const int bottom_sb = bottom_sb_visible(); - - fl_push_clip( x(), y() + ( sbh * top_sb ), w(), h() - (sbh * (top_sb + bottom_sb) )); - - draw_children(); - - fl_pop_clip(); - - fl_font( FL_HELVETICA, 12 ); - - if ( top_sb ) - { - fl_draw_box( box(), x(), y(), w(), sbh, color() ); - fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); - fl_draw( "@2<", x(), y(), w(), sbh, FL_ALIGN_CENTER ); - } - - if ( bottom_sb ) - { - fl_draw_box( box(), x(), y() + h() - sbh, w(), sbh, color() ); - fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); - fl_draw( "@2>", x(), y() + h() - sbh, w(), sbh, FL_ALIGN_CENTER ); - } - } - - virtual int - handle ( int m ) - { - switch ( m ) - { - case FL_PUSH: - if ( top_sb_visible() && - Fl::event_inside( x(), y(), w(), sbh ) ) - { - return 1; - } - else if ( bottom_sb_visible() && - Fl::event_inside( x(), y() + h() - sbh, w(), sbh ) ) - { - return 1; - } - break; - case FL_RELEASE: - { - if ( top_sb_visible() && - Fl::event_inside( x(), y(), w(), sbh ) ) - { - yposition( yposition() + ( h() / 4 ) ); - return 1; - } - else if ( bottom_sb_visible() && - Fl::event_inside( x(), y() + h() - sbh, w(), sbh ) ) - { - yposition( yposition() - (h() / 4 ) ); - return 1; - } - break; - } - case FL_KEYBOARD: - { - if ( Fl::event_key() == FL_Up ) - { - yposition( yposition() + ( h() / 4 ) ); - return 1; - } - else if ( Fl::event_key() == FL_Down ) - { - yposition( yposition() - (h() / 4 ) ); - return 1; - } - break; - } - case FL_MOUSEWHEEL: - { - yposition( yposition() - ( Fl::event_dy() * _increment ) ); - - return 1; - } - } - - return Fl_Group::handle( m ); - } -}; diff --git a/FL/Fl_Scalepack.C b/FL/Fl_Scalepack.C deleted file mode 100644 index c253838..0000000 --- a/FL/Fl_Scalepack.C +++ /dev/null @@ -1,250 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -/* Fl_Scalepack - - This is similar to an Fl_Pack, but instead of the pack resizing - itself to enclose its children, this pack resizes its children to - fit itself. Of course, this only works well with highly flexible - widgets, but the task comes up often enough to warrent this class. - - If and child happens to be the resizable() widget, then it will be - resized so the all the other children can fit around it, with their - current sizes (and the size of the Fl_Scalepack) maintained. - - NOTES: An Fl_Pack as a direct child will not work, because Fl_Pack - changes its size in draw(), which throws off our resize - calculation. The whole idea of widgets being able to resize - themselves within draw() is horribly broken... -*/ - -#include "Fl_Scalepack.H" - -#include -#include -#include - -Fl_Scalepack::Fl_Scalepack ( int X, int Y, int W, int H, const char *L ) : - Fl_Group( X, Y, W, H, L ) -{ - resizable( 0 ); - _spacing = 0; -} - -void -Fl_Scalepack::resize ( int X, int Y, int W, int H ) -{ - /* Fl_Group's resize will change our child widget sizes, which - interferes with our own resizing method. */ - long dx = X - x(); - long dy = Y - y(); - - bool r = W != w() || H != h(); - - Fl_Widget::resize( X, Y, W, H ); - - Fl_Widget*const* a = array(); - - for (int i=children(); i--;) - { - Fl_Widget* o = *a++; - - o->position( o->x() + dx, o->y() + dy ); - } - - if ( r ) - redraw(); -} - -void -Fl_Scalepack::draw ( void ) -{ - - if ( resizable() == this ) - /* this resizable( this ) is the default for Fl_Group and is - * reset by Fl_Group::clear(), but it is not our default... */ - resizable( 0 ); - - int tx = x() + Fl::box_dx( box() ); - int ty = y() + Fl::box_dy( box() ); - int tw = w() - Fl::box_dw( box() ); - int th = h() - Fl::box_dh( box() ); - - if ( damage() & FL_DAMAGE_ALL ) - { - draw_box(); - - draw_label(); - } - - int v = 0; - - int cth = 0; - int ctw = 0; - - Fl_Widget * const * a = array(); - - for ( int i = children(); i--; ) - { - Fl_Widget *o = *a++; - - if ( o->visible() ) - { - ++v; - - if ( o != this->resizable() ) - { - cth += o->h(); - ctw += o->w(); - } - - cth += _spacing; - ctw += _spacing; - } - } - - ctw -= _spacing; - cth -= _spacing; - - if ( 0 == v ) - return; - - if ( this->resizable() ) - { - int pos = 0; - - Fl_Widget * const * a = array(); - - for ( int i = children(); i--; ) - { - Fl_Widget *o = *a++; - - if ( o->visible() ) - { - int X, Y, W, H; - - if ( type() == HORIZONTAL ) - { - X = tx + pos; - Y = ty; - W = o->w(); - H = th; - } - else - { - X = tx; - Y = ty + pos; - W = tw; - H = o->h(); - } - - if ( this->resizable() == o ) - { - if ( type() == HORIZONTAL ) - W = tw - ctw - 3; - else - H = th - cth; - } - - if (X != o->x() || Y != o->y() || W != o->w() || H != o->h() ) - { - o->resize(X,Y,W,H); - o->clear_damage(FL_DAMAGE_ALL); - } - - if ( damage() & FL_DAMAGE_ALL ) - { - draw_child( *o ); - draw_outside_label( *o ); - } - else - update_child( *o ); - -/* if ( this->resizable() == o ) */ -/* fl_rect( o->x(), o->y(), o->w(), o->h(), type() == VERTICAL ? FL_GREEN : FL_BLUE ); */ - - if ( type() == HORIZONTAL ) - pos += o->w() + spacing(); - else - pos += o->h() + spacing(); - - } - } - } - else - { - int sz = 0; - int pos = 0; - - if ( type() == HORIZONTAL ) - sz = (tw - (_spacing * (v - 1))) / v; - else - sz = (th - (_spacing * (v - 1))) / v; - - Fl_Widget * const * a = array(); - - for ( int i = children(); i--; ) - { - Fl_Widget *o = *a++; - - if ( o->visible() ) - { - int X, Y, W, H; - - if ( type() == HORIZONTAL ) - { - X = tx + pos; - Y = ty; - W = sz; - H = th; - } - else - { - X = tx; - Y = ty + pos; - W = tw; - H = sz; - } - - if (X != o->x() || Y != o->y() || W != o->w() || H != o->h() ) - { - o->resize(X,Y,W,H); - o->clear_damage(FL_DAMAGE_ALL); - } - - if ( damage() & FL_DAMAGE_ALL ) - { - draw_child( *o ); - draw_outside_label( *o ); - } - else - update_child( *o ); - -// fl_rect( o->x(), o->y(), o->w(), o->h(), type() == VERTICAL ? FL_RED : FL_YELLOW ); - - if ( type() == HORIZONTAL ) - pos += o->w() + spacing(); - else - pos += o->h() + spacing(); - - } - } - } -} diff --git a/FL/Fl_Scalepack.H b/FL/Fl_Scalepack.H deleted file mode 100644 index 9974bba..0000000 --- a/FL/Fl_Scalepack.H +++ /dev/null @@ -1,43 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -class Fl_Scalepack : public Fl_Group -{ - - int _spacing; - -public: - - enum { VERTICAL, HORIZONTAL }; - - Fl_Scalepack ( int X, int Y, int W, int H, const char *L = 0 ); - virtual ~Fl_Scalepack ( ) { } - - int spacing ( void ) const { return _spacing; } - void spacing ( int v ) { _spacing = v; redraw(); } - - virtual void resize ( int, int, int, int ); - - virtual void draw ( void ); - -}; diff --git a/FL/Fl_SliderX.C b/FL/Fl_SliderX.C deleted file mode 100644 index 582b02a..0000000 --- a/FL/Fl_SliderX.C +++ /dev/null @@ -1,341 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Fl_SliderX.H" -#include -#include - -#include - -void -Fl_SliderX::draw ( int X, int Y, int W, int H) -{ - slider_size( horizontal() ? H / (float)W : W / (float)H ); - - int act = active_r(); - - if (damage()&FL_DAMAGE_ALL) draw_box(); - - - int ww = (horizontal() ? W : H); - int hh = (horizontal() ? H : W); - int xx, S; - - xx = slider_position( value(), ww ); - - S = (horizontal() ? H : W ); - - int xsl, ysl, wsl, hsl; - if (horizontal()) { - xsl = X+xx; - wsl = S; - ysl = Y + hh/2; - hsl = hh/4; - } else { - ysl = Y+xx; - hsl = S; - xsl = X + hh/2; - wsl = hh/4; - } - - { - fl_push_clip(X, Y, W, H); - draw_box(); - fl_pop_clip(); - } - //draw_bg(X, Y, W, H); - - fl_line_style( FL_SOLID, hh/6 ); - - Fl_Color c = fl_darker(color()); - - if ( !act ) - c = fl_inactive(c); - - fl_color(c); - - if ( horizontal() ) - fl_line ( X + S/2, Y + hh/2, X + W - S/2, Y + hh/2 ); - else - fl_line ( X + hh/2, Y + S/2, X + hh/2, Y + H - S/2 ); - - c = selection_color(); - - if ( !act ) - c = fl_inactive(c); - - fl_color( c ); - - if ( horizontal() ) - fl_line ( X + S/2, ysl, xsl + S/2, ysl ); - else - fl_line ( X + S/2, Y + H - S/2, xsl, ysl + (S/2) ); - - fl_line_style( FL_SOLID, 0 ); - - if ( act ) - { - fl_push_matrix(); - if ( horizontal() ) - fl_translate( xsl + (hh/2), ysl); - else - fl_translate( xsl, ysl + (hh/2) ); - - fl_color( fl_color_add_alpha( FL_WHITE, 127 )); - fl_begin_polygon(); fl_circle(0.0,0.0, hh/3); fl_end_polygon(); - fl_color( FL_WHITE ); - fl_begin_polygon(); fl_circle(0.0,0.0, hh/6); fl_end_polygon(); - - fl_pop_matrix(); - } - - draw_label(xsl, ysl, wsl, hsl); - - if (Fl::focus() == this) { - draw_focus(); - } - - /* draw(x()+Fl::box_dx(box()), */ - /* y()+Fl::box_dy(box()), */ - /* w()-Fl::box_dw(box()), */ - /* h()-Fl::box_dh(box())); */ - -} - -/** return a value between 0.0 and 1.0 which represents the current slider position. */ -int -Fl_SliderX::slider_position ( double value, int w ) -{ - double A = minimum(); - double B = maximum(); - if (B == A) return 0; - bool flip = B < A; - if (flip) {A = B; B = minimum();} -// if (!horizontal()) flip = !flip; - // if both are negative, make the range positive: - if (B <= 0) {flip = !flip; double t = A; A = -B; B = -t; value = -value;} - double fraction; - if (!log()) { - // linear slider - fraction = (value-A)/(B-A); - } else if (A > 0) { - // logatithmic slider - if (value <= A) fraction = 0; - else fraction = (::log(value)-::log(A))/(::log(B)-::log(A)); - } else if (A == 0) { - // squared slider - if (value <= 0) fraction = 0; - else fraction = sqrt(value/B); - } else { - // squared signed slider - if (value < 0) fraction = (1-sqrt(value/A))*.5; - else fraction = (1+sqrt(value/B))*.5; - } - if (flip) fraction = 1-fraction; - - w -= int(slider_size()*w+.5); if (w <= 0) return 0; - if (fraction >= 1) return w; - else if (fraction <= 0) return 0; - else return int(fraction*w+.5); -} - -double -Fl_SliderX::slider_value ( int X, int w ) -{ - w -= int(slider_size()*w+.5); if (w <= 0) return minimum(); - double A = minimum(); - double B = maximum(); - bool flip = B < A; - if (flip) {A = B; B = minimum();} -// if (!horizontal()) flip = !flip; - if (flip) X = w-X; - double fraction = double(X)/w; - if (fraction <= 0) return A; - if (fraction >= 1) return B; - // if both are negative, make the range positive: - flip = (B <= 0); - if (flip) {double t = A; A = -B; B = -t; fraction = 1-fraction;} - double value; - double derivative; - if (!log()) { - // linear slider - value = fraction*(B-A)+A; - derivative = (B-A)/w; - } else if (A > 0) { - // log slider - double d = (::log(B)-::log(A)); - value = exp(fraction*d+::log(A)); - derivative = value*d/w; - } else if (A == 0) { - // squared slider - value = fraction*fraction*B; - derivative = 2*fraction*B/w; - } else { - // squared signed slider - fraction = 2*fraction - 1; - if (fraction < 0) B = A; - value = fraction*fraction*B; - derivative = 4*fraction*B/w; - } - // find nicest multiple of 10,5, or 2 of step() that is close to 1 pixel: - if (step() && derivative > step()) { - double w = log10(derivative); - double l = ceil(w); - int num = 1; - int i; for (i = 0; i < l; i++) num *= 10; - int denom = 1; - for (i = -1; i >= l; i--) denom *= 10; - if (l-w > 0.69897) denom *= 5; - else if (l-w > 0.30103) denom *= 2; - value = floor(value*denom/num+.5)*num/denom; - } - if (flip) return -value; - return value; - -} - -int Fl_SliderX::handle(int event, int X, int Y, int W, int H) { - // Fl_Widget_Tracker wp(this); - switch (event) { - case FL_PUSH: { - Fl_Widget_Tracker wp(this); - if (!Fl::event_inside(X, Y, W, H)) return 0; - handle_push(); - if (wp.deleted()) return 1; } - // fall through ... - case FL_DRAG: { - - static int offcenter; - - int ww = (horizontal() ? W : H); - - if ( event == FL_PUSH ) - { - int x = slider_position( value(), ww ); - - offcenter = (horizontal() ? (Fl::event_x()-X) - x : (Fl::event_y()-Y) - x ); - } - - try_again: - - int mx = (horizontal() ? Fl::event_x()-X : Fl::event_y()-Y) - offcenter; - double v = slider_value( mx, ww ); - - if (event == FL_PUSH ) // && v == value()) { - { - int os = int(slider_size()*ww+0.5)/2; - if ( abs( offcenter ) > os ) - { - offcenter = os; - event = FL_DRAG; - goto try_again; - } - } - - handle_drag(clamp(v)); - } return 1; - case FL_RELEASE: - handle_release(); - return 1; - case FL_KEYBOARD: - { Fl_Widget_Tracker wp(this); - switch (Fl::event_key()) { - case FL_Up: - if (horizontal()) return 0; - handle_push(); - if (wp.deleted()) return 1; - handle_drag(clamp(increment(value(),-1))); - if (wp.deleted()) return 1; - handle_release(); - return 1; - case FL_Down: - if (horizontal()) return 0; - handle_push(); - if (wp.deleted()) return 1; - handle_drag(clamp(increment(value(),1))); - if (wp.deleted()) return 1; - handle_release(); - return 1; - case FL_Left: - if (!horizontal()) return 0; - handle_push(); - if (wp.deleted()) return 1; - handle_drag(clamp(increment(value(),-1))); - if (wp.deleted()) return 1; - handle_release(); - return 1; - case FL_Right: - if (!horizontal()) return 0; - handle_push(); - if (wp.deleted()) return 1; - handle_drag(clamp(increment(value(),1))); - if (wp.deleted()) return 1; - handle_release(); - return 1; - default: - return 0; - } - } - // break not required because of switch... - case FL_FOCUS : - case FL_UNFOCUS : - if (Fl::visible_focus()) { - redraw(); - return 1; - } else return 0; - case FL_ENTER : - case FL_LEAVE : - return 1; - case FL_MOUSEWHEEL : - { - if ( this != Fl::belowmouse() ) - return 0; - if (Fl::e_dy==0) - return 0; - - const int steps = Fl::event_ctrl() ? 128 : 16; - - const float step = fabs( maximum() - minimum() ) / (float)steps; - - int dy = Fl::e_dy; - - /* slider is in 'upside down' configuration, invert meaning of mousewheel */ - if ( minimum() > maximum() ) - dy = 0 - dy; - - handle_drag(clamp(value() + step * dy)); - return 1; - } - default: - return 0; - } -} - -int Fl_SliderX::handle(int event) { - if (event == FL_PUSH && Fl::visible_focus()) { - Fl::focus(this); - redraw(); - } - - return handle(event, - x()+Fl::box_dx(box()), - y()+Fl::box_dy(box()), - w()-Fl::box_dw(box()), - h()-Fl::box_dh(box())); -} diff --git a/FL/Fl_SliderX.H b/FL/Fl_SliderX.H deleted file mode 100644 index bc56605..0000000 --- a/FL/Fl_SliderX.H +++ /dev/null @@ -1,50 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -class Fl_SliderX : public Fl_Slider -{ - bool _log; - - -public: - - void log ( bool v ) { _log = v; } - bool log ( void ) const { return _log; } - - Fl_SliderX( int X, int Y, int W, int H, const char *L=0 ) : Fl_Slider(X,Y,W,H,L) - { - _log = 0; - } - - virtual ~Fl_SliderX ( ) { }; - - virtual int slider_position ( double value, int w ); - virtual double slider_value ( int X, int w ); - - virtual void draw ( int X, int Y, int W, int H ); - virtual void draw ( void ) { draw(x(),y(),w(),h()); } - - - virtual int handle(int event, int X, int Y, int W, int H); - virtual int handle(int event); -}; diff --git a/FL/Fl_Sometimes_Input.H b/FL/Fl_Sometimes_Input.H deleted file mode 100644 index ef5be75..0000000 --- a/FL/Fl_Sometimes_Input.H +++ /dev/null @@ -1,113 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -/* Just like an Fl_Input, except that when not being edited it - * displays just like a label. */ - -#include -#include -#include -#include - -class Fl_Sometimes_Input : public Fl_Input -{ - Fl_Boxtype _up_box; - -public: - - Fl_Sometimes_Input ( int X, int Y, int W, int H, const char *L=0 ) - : Fl_Input( X, Y, W, H, L ) - { - clear_visible_focus(); - up_box( FL_NO_BOX ); - when(FL_WHEN_ENTER_KEY); - } - - void up_box ( Fl_Boxtype b ) { _up_box = b; } - Fl_Boxtype up_box ( void ) const { return _up_box; } - - virtual void - draw ( void ) - { - if ( this == Fl::focus() ) - Fl_Input::draw(); - else - { - fl_draw_box( up_box(), x(), y(), w(), h(), color() ); - - Fl_Color c = fl_contrast( textcolor(), color() ); - - fl_color( active_r() ? c : fl_inactive( c ) ); - - fl_font( textfont(), textsize() ); - fl_draw( value(), x(), y(), w(), h(), (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_CLIP) ); - } - } - - virtual void - take_focus ( void ) - { - set_visible_focus(); - Fl_Widget::take_focus(); - clear_visible_focus(); - } - - virtual int - handle ( int m ) - { - int r = 0; - - switch ( m ) - { - case FL_KEYDOWN: - { - if ( ( Fl::event_key() == FL_Enter || - Fl::event_key() == FL_Tab ) ) - { - Fl::focus( NULL ); - r = 1; - } - break; - } - case FL_FOCUS: - redraw(); - r = 1; - break; - case FL_UNFOCUS: - do_callback(); - r = 1; - break; - case FL_PUSH: - take_focus(); - redraw(); - r = 1; - break; - case FL_DND_ENTER: - return 0; - case FL_PASTE: - return 0; - default: - break; - } - - return Fl_Input::handle( m ) | r; - } -}; diff --git a/FL/Fl_Sometimes_Pack.H b/FL/Fl_Sometimes_Pack.H deleted file mode 100644 index d20a035..0000000 --- a/FL/Fl_Sometimes_Pack.H +++ /dev/null @@ -1,76 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -class Fl_Sometimes_Pack : public Fl_Pack -{ - bool _pack; - -public: - - Fl_Sometimes_Pack ( int X, int Y, int W, int H, const char *L=0 ) : Fl_Pack(X,Y,W,H,L) - { - _pack = true; - } - - virtual ~Fl_Sometimes_Pack ( ) - { - } - - void pack ( bool b ) - { - if ( b != _pack ) - redraw(); - - _pack = b; - } - - bool pack ( void ) const - { - return _pack; - } - - virtual void draw ( void ) - { - /* draw_box(); */ - - if ( _pack ) - { - Fl_Pack::draw(); - } - else - { - if ( children() ) - { - for ( int i = 0; i < children(); i++ ) - { - Fl_Widget *o = child( i ); - - o->resize( x(),y(),w(), o->h() ); - } - resize( x(), y(), w(), child(0)->h() ); - } - - Fl_Group::draw(); - } - } -}; diff --git a/FL/Fl_Text_Edit_Window.fl b/FL/Fl_Text_Edit_Window.fl deleted file mode 100644 index 8e95597..0000000 --- a/FL/Fl_Text_Edit_Window.fl +++ /dev/null @@ -1,53 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -decl {\#include } {private local -} - -widget_class Fl_Text_Edit_Window {open - xywh {377 295 355 410} type Double resizable - code0 {this->size_range( 0, 0, 400, 400 );} - class Fl_Double_Window modal visible -} { - Fl_Box title_box { - label {} - xywh {5 7 345 28} - } - Fl_Text_Editor text_editor {selected - xywh {5 37 345 341} resizable - code0 {o->buffer( new Fl_Text_Buffer );} - } - Fl_Group {} {open - xywh {5 383 345 27} - } { - Fl_Return_Button return_button { - label {<return>} - callback {hide();} - xywh {250 383 100 25} - } - Fl_Box {} { - label {<empty>} - xywh {5 386 240 19} resizable - code0 {o->labeltype( FL_NO_LABEL );} - } - } -} - -Function {fl_text_edit( const char *title, const char *button_text, const char *initial_text, int W = 355, int H = 410 )} {open C return_type {char *} -} { - code {Fl_Text_Edit_Window tew( 355, 410, title ); - -tew.size( W, H ); -tew.return_button->label( button_text ); -tew.title_box->label( title ); -if ( initial_text ) - tew.text_editor->buffer()->text( initial_text ); - -tew.show(); - -while ( tew.shown() ) - Fl::wait(); - -return strdup( tew.text_editor->buffer()->text() );} {} -} diff --git a/FL/Fl_Value_SliderX.C b/FL/Fl_Value_SliderX.C deleted file mode 100644 index 0e8821f..0000000 --- a/FL/Fl_Value_SliderX.C +++ /dev/null @@ -1,234 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#include "Fl_Value_SliderX.H" - -#include <FL/Fl.H> -#include <FL/fl_draw.H> -#include <math.h> - -void Fl_Value_SliderX::input_cb(Fl_Widget*, void* v) { - Fl_Value_SliderX& t = *(Fl_Value_SliderX*)v; - double nv; - if ((t.step() - floor(t.step()))>0.0 || t.step() == 0.0) - nv = strtod(t.input.value(), 0); - else - nv = strtol(t.input.value(), 0, 0); - - if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) { - - if ( ! t.soft()) - nv = t.clamp(nv); - t.set_value(nv); - t.set_changed(); - if (t.when()) - { - t.value_damage(); - t.do_callback(); - } - } -} - -void Fl_Value_SliderX::value_damage() { - char buf[128]; - format(buf); - input.value(buf); - input.mark(input.position()); // turn off selection highlight - redraw(); -} - - -Fl_Value_SliderX::~Fl_Value_SliderX ( void ) -{ - if (input.parent() == (Fl_Group *)this) - input.parent(0); // *revert* ctor kludge! -} - -/** - Creates a new Fl_Value_SliderX widget using the given - position, size, and label string. The default boxtype is FL_DOWN_BOX. -*/ -Fl_Value_SliderX::Fl_Value_SliderX(int X, int Y, int W, int H, const char*l) - : Fl_SliderX(X,Y,W,H,l),input(X, Y, W, H, 0) { - step(1,100); - - soft_ = 0; - if (input.parent()) // defeat automatic-add - input.parent()->remove(input); - input.parent((Fl_Group *)this); // kludge! - input.callback(input_cb, this); - input.when(FL_WHEN_ENTER_KEY); - align(FL_ALIGN_LEFT); - value_damage(); - textsize(9); - set_flag(SHORTCUT_LABEL); - -} - -void Fl_Value_SliderX::draw() { - - int sxx = x(), syy = y(), sww = w(), shh = h(); - int bxx = x(), byy = y(), bww = w(), bhh = h(); - if (horizontal()) { - input.resize(x(), y(), 35, h()); - bww = 35; sxx += 35; sww -= 35; - } else { - input.resize(x(), y(), w(), 25 ); - syy += 25; bhh = 25; shh -= 25; - } - if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color()); - Fl_SliderX::draw(sxx+Fl::box_dx(box()), - syy+Fl::box_dy(box()), - sww-Fl::box_dw(box()), - shh-Fl::box_dh(box())); - draw_box(box(),bxx,byy,bww,bhh,color()); - - if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL); - input.box(box()); - input.color(color(), selection_color()); - Fl_Widget *i = &input; i->draw(); // calls protected input.draw() - input.clear_damage(); -} - -int Fl_Value_SliderX::handle(int event) { - if (event == FL_PUSH && Fl::visible_focus()) { - Fl::focus(this); - redraw(); - } - - int sxx = x(), syy = y(), sww = w(), shh = h(); - if (horizontal()) { - sxx += 35; sww -= 35; - } else { - syy += 25; shh -= 25; - } - - double v; - int delta; - int mx = Fl::event_x_root(); - static int ix, drag; -// input.when(when()); - switch (event) { - case FL_ENTER: - return 1; - case FL_LEAVE: - if ( ! drag ) - fl_cursor( FL_CURSOR_DEFAULT ); - return 1; - case FL_MOVE: - if ( drag || Fl::event_inside( &input ) ) - fl_cursor( FL_CURSOR_WE ); - else - fl_cursor( FL_CURSOR_DEFAULT ); - return 1; - case FL_PUSH: -// if (!step()) goto DEFAULT; - if ( Fl::event_inside(&input) ) - { - input.handle(event); - ix = mx; - drag = Fl::event_button(); - handle_push(); - return 1; - } - goto DEFAULT; - break; - case FL_DRAG: - { - if ( ! drag ) - goto DEFAULT; - - fl_cursor( FL_CURSOR_WE ); - -// if (!step()) goto DEFAULT; - delta = mx-ix; - if (!horizontal()) - delta = -delta; - - if (delta > 5) delta -= 5; - else if (delta < -5) delta += 5; - else delta = 0; - - float S = fabs( maximum() - minimum() ); - - switch (drag) { - case 3: v = previous_value() + ( S * delta * 0.0100f); break; - case 2: v = previous_value() + ( S * delta * 0.0010f); break; - default:v = previous_value() + ( S * delta * 0.0005f); break; - } - - v = round(v); - v = soft()?softclamp(v):clamp(v); - handle_drag(v); - value_damage(); - return 1; - } - case FL_RELEASE: - - if ( ! drag ) - goto DEFAULT; - - // if (!step()) goto DEFAULT; - if (value() != previous_value() || !Fl::event_is_click()) - handle_release(); - - drag = 0; - - fl_cursor( FL_CURSOR_DEFAULT ); - - /* else { */ - /* Fl_Widget_Tracker wp(&input); */ - /* input.handle(FL_PUSH); */ - /* if (wp.exists()) */ - /* input.handle(FL_RELEASE); */ - /* } */ - return 1; - case FL_FOCUS: - return input.take_focus(); - case FL_UNFOCUS: - { - input_cb(&input,this); - return 1; - } - case FL_PASTE: - return 0; - case FL_SHORTCUT: - return input.handle(event); - } - -DEFAULT: - - int r = Fl_SliderX::handle(event, - sxx+Fl::box_dx(box()), - syy+Fl::box_dy(box()), - sww-Fl::box_dw(box()), - shh-Fl::box_dh(box())); - - if ( r ) - { - return r; - } - else - { - input.type(((step() - floor(step()))>0.0 || step() == 0.0) ? FL_FLOAT_INPUT : FL_INT_INPUT); - return input.handle(event); - } -} - diff --git a/FL/Fl_Value_SliderX.H b/FL/Fl_Value_SliderX.H deleted file mode 100644 index 39492b0..0000000 --- a/FL/Fl_Value_SliderX.H +++ /dev/null @@ -1,100 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#ifndef Fl_Value_SliderX_H -#define Fl_Value_SliderX_H - -#include "Fl_SliderX.H" -#include <FL/Fl_Input.H> - -/** - The Fl_Value_SliderX widget is a Fl_SliderX widget - with a box displaying the current value. - <P ALIGN=CENTER>\image html value_slider.png - \image latex value_slider.png "Fl_Value_SliderX" width=4cm -*/ -class FL_EXPORT Fl_Value_SliderX : public Fl_SliderX { - /* This is the encapsulated Fl_input attribute to which - this class delegates the value font, color and shortcut */ - Fl_Input input; - -private: - char soft_; - static void input_cb(Fl_Widget*,void*); - virtual void value_damage(); // cause damage() due to value() changing - -protected: - void draw(); -public: - int handle(int); - Fl_Value_SliderX(int x,int y,int w,int h, const char *l = 0); - virtual ~Fl_Value_SliderX ( ); - -/** See void Fl_Value_Input::soft(char s) */ - void soft(char s) {soft_ = s;} - /** - If "soft" is turned on, the user is allowed to drag - the value outside the range. If they drag the value to one of - the ends, let go, then grab again and continue to drag, they can - get to any value. The default is true. - */ - char soft() const {return soft_;} - /** - Returns the current shortcut key for the Input. - \see Fl_Value_Input::shortcut(int) - */ - int shortcut() const {return input.shortcut();} - /** - Sets the shortcut key to \p s. Setting this - overrides the use of '&' in the label(). The value is a bitwise - OR of a key and a set of shift flags, for example FL_ALT | 'a' - , FL_ALT | (FL_F + 10), or just 'a'. A value - of 0 disables the shortcut. - - The key can be any value returned by - Fl::event_key(), but will usually be an ASCII letter. Use - a lower-case letter unless you require the shift key to be held down. - - The shift flags can be any set of values accepted by - Fl::event_state(). If the bit is on that shift key must - be pushed. Meta, Alt, Ctrl, and Shift must be off if they are not in - the shift flags (zero for the other bits indicates a "don't care" - setting). - */ - void shortcut(int s) {input.shortcut(s);} - /** Gets the typeface of the text in the value box. */ - Fl_Font textfont() const {return input.textfont();} - /** Sets the typeface of the text in the value box. */ - void textfont(Fl_Font s) {input.textfont(s);} - /** Gets the size of the text in the value box. */ - Fl_Fontsize textsize() const {return input.textsize();} - /** Sets the size of the text in the value box. */ - void textsize(Fl_Fontsize s) {input.textsize(s);} - /** Gets the color of the text in the value box. */ - Fl_Color textcolor() const {return input.textcolor();} - /** Sets the color of the text in the value box.*/ - void textcolor(Fl_Color n) {input.textcolor(n);} - /** Gets the color of the text cursor. The text cursor is black by default. */ - Fl_Color cursor_color() const {return input.cursor_color();} - /** Sets the color of the text cursor. The text cursor is black by default. */ - void cursor_color(Fl_Color n) {input.cursor_color(n);} -}; - -#endif - diff --git a/FL/New_Project_Dialog.fl b/FL/New_Project_Dialog.fl deleted file mode 100644 index 14be033..0000000 --- a/FL/New_Project_Dialog.fl +++ /dev/null @@ -1,132 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -comment {// -// Copyright (C) 2008 Jonathan Moore Liles -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -} {in_source in_header -} - -decl {\#include <stdlib.h>} {private local -} - -decl {\#include <string.h>} {private local -} - -decl {\#include <stdio.h>} {private local -} - -decl {\#include <FL/Fl_File_Chooser.H>} {private local -} - -class New_Project_Dialog {open -} { - Function {New_Project_Dialog()} {open - } { - code {_default_path = 0; -path = 0; -make_window();} {} - } - Function {run()} {open return_type void - } { - code {_directory->value( _default_path ); - -_window->show(); - -while ( _window->shown() ) - Fl::wait();} {} - } - Function {make_window()} {open - } { - Fl_Window _window { - label {New Project} open selected - xywh {743 696 550 105} type Double modal visible - } { - Fl_File_Input _name { - label {Named:} - xywh {75 55 375 35} - } - Fl_Button {} { - label Browse - callback {_directory->value( fl_dir_chooser( "Directory for new project", NULL, 0 ) );} - xywh {455 15 80 35} - } - Fl_Return_Button {} { - label Create - callback {if ( strlen( _directory->value() ) && strlen( _name->value() ) ) -{ - char pat[1024]; - - snprintf( pat, sizeof( pat ), "%s/%s", _directory->value(), _name->value() ); - - path = strdup( pat ); - - _default_path = _directory->value() ? strdup( _directory->value() ) : 0; - - //if ( ! Project::create( pat, _template->text( _template->value() ) ) ) - // fl_alert( "Error creating project!" ); - - _window->hide(); -}} - xywh {455 55 80 35} - } - Fl_File_Input _directory { - label {Where:} - callback {if ( ! fl_filename_isdir( o->value() ) ) -{ - fl_alert( "Must be a directory" ); - o->value( "" ); - return; -} - -// write_line( user_config_dir, "default_path", o->value() );} - xywh {75 15 375 35} - code0 {\#include <FL/filename.H>} - code1 {char *v = NULL;} - code2 {// read_line( user_config_dir, "default_path", &v );} - code3 {o->value( v );} - } - } - } - decl {char *path;} {public local - } - decl {char *_default_path} {private local - } - Function {default_path( char *s )} {open return_type void - } { - code {_default_path = s;} {} - } - Function {default_path()} {open return_type {char *} - } { - code {return _default_path;} {} - } -} - -Function {new_project_chooser( char **default_path)} {open C return_type {char*} -} { - code {New_Project_Dialog nsd; - -nsd.default_path( *default_path ); - -nsd.run(); - -if ( nsd.default_path() ) - *default_path = nsd.default_path(); - -return nsd.path;} {} -} diff --git a/FL/event_name.C b/FL/event_name.C deleted file mode 100644 index d53ab98..0000000 --- a/FL/event_name.C +++ /dev/null @@ -1,52 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -static const char *event_names[] = -{ - "FL_NO_EVENT", - "FL_PUSH", - "FL_RELEASE", - "FL_ENTER", - "FL_LEAVE", - "FL_DRAG", - "FL_FOCUS", - "FL_UNFOCUS", - "FL_KEYDOWN", - "FL_KEYUP", - "FL_CLOSE", - "FL_MOVE", - "FL_SHORTCUT", - "FL_DEACTIVATE", - "FL_ACTIVATE", - "FL_HIDE", - "FL_SHOW", - "FL_PASTE", - "FL_SELECTIONCLEAR", - "FL_MOUSEWHEEL", - "FL_DND_ENTER", - "FL_DND_DRAG", - "FL_DND_LEAVE", - "FL_DND_RELEASE", -}; - -const char * -event_name ( int m ) -{ - return event_names[ m ]; -} diff --git a/FL/event_name.H b/FL/event_name.H deleted file mode 100644 index 28d58d6..0000000 --- a/FL/event_name.H +++ /dev/null @@ -1,20 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -const char *event_name ( int m ); diff --git a/FL/focus_frame.C b/FL/focus_frame.C deleted file mode 100644 index 0cabb7e..0000000 --- a/FL/focus_frame.C +++ /dev/null @@ -1,103 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include <FL/Fl.H> -#include <FL/fl_draw.H> - -void -draw_focus_frame ( int x, int y, int w, int h, Fl_Color c ) -{ - fl_push_clip( x, y, w, h ); - -// fl_color( fl_color_average( FL_GRAY, c, 0.50 ) ); - - /* fl_color( fl_color_add_alpha( c, 100 ) ); */ - - /* fl_line_style( FL_DASH, 2 ); */ - - /* fl_rect( x, y, w, h ); */ - - fl_line_style( FL_SOLID, 3 ); - - fl_color( c ); - - int l = 15; - - fl_line( x, y, x + l, y ); - fl_line( x, y + l, x, y ); - - fl_line( x + w - 1, y, x + w - l - 1, y ); - fl_line( x + w - 1, y, x + w - 1, y + l - 1 ); - - fl_line( x, y + h - 1, x, y + h - l - 1); - fl_line( x, y + h - 1, x + l, y + h - 1 ); - - fl_line( x + w - 1, y + h - 1, x + w - 1, y + h - l - 1 ); - fl_line( x + w - 1, y + h - 1, x + w - l, y + h - 1 ); - - fl_line_style( FL_SOLID, 0 ); - - fl_pop_clip(); -} - -void -draw_selection_frame ( int x, int y, int w, int h, Fl_Color c ) -{ - fl_push_clip( x, y, w, h ); - - fl_color( fl_color_average( FL_GRAY, c, 0.50 ) ); - -/// fl_color( fl_color_add_alpha( c, 100 ) ); - - fl_line_style( FL_DASH, 2 ); - - fl_rect( x, y, w, h ); - - fl_line_style( FL_SOLID, 3 ); - - fl_color( c ); - - int l = 15; - - fl_line( x, y, x + l, y ); - fl_line( x, y + l, x, y ); - - fl_line( x + w - 1, y, x + w - l - 1, y ); - fl_line( x + w - 1, y, x + w - 1, y + l - 1 ); - - fl_line( x, y + h - 1, x, y + h - l - 1); - fl_line( x, y + h - 1, x + l, y + h - 1 ); - - fl_line( x + w - 1, y + h - 1, x + w - 1, y + h - l - 1 ); - fl_line( x + w - 1, y + h - 1, x + w - l, y + h - 1 ); - - fl_line_style( FL_SOLID, 0 ); - - fl_pop_clip(); -} - -bool -focused_r ( Fl_Widget *w ) -{ - for ( Fl_Widget *p = Fl::focus(); p; p = p->parent() ) - if ( p == w ) - return true; - - return false; -} diff --git a/FL/focus_frame.H b/FL/focus_frame.H deleted file mode 100644 index e48e540..0000000 --- a/FL/focus_frame.H +++ /dev/null @@ -1,22 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -void draw_focus_frame ( int x, int y, int w, int h, Fl_Color c ); -void draw_selection_frame ( int x, int y, int w, int h, Fl_Color c ); -bool focused_r ( Fl_Widget *w ); diff --git a/FL/img_io_input_connector_10x10_png.h b/FL/img_io_input_connector_10x10_png.h deleted file mode 100644 index c58f485..0000000 --- a/FL/img_io_input_connector_10x10_png.h +++ /dev/null @@ -1,61 +0,0 @@ -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -static unsigned char img_io_input_connector_10x10_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, - 0x08, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x32, 0xcf, 0xbd, 0x00, 0x00, 0x00, - 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, - 0x88, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x00, - 0x9e, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x22, 0xcb, 0xc6, 0x03, 0x00, 0x00, - 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, - 0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, - 0x00, 0x01, 0x51, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x3d, 0xd0, 0xb1, - 0x6a, 0xdb, 0x40, 0x1c, 0xc0, 0xe1, 0x9f, 0x72, 0x7f, 0xcc, 0x21, 0xbc, - 0xc5, 0x87, 0xb0, 0xb7, 0x18, 0x6c, 0xa8, 0x49, 0x37, 0x1b, 0x8c, 0x26, - 0xdb, 0x19, 0xfb, 0x0e, 0x7e, 0x82, 0xee, 0x21, 0x53, 0xe9, 0x14, 0x42, - 0x37, 0x37, 0x7b, 0x9e, 0xa2, 0x63, 0x07, 0x6b, 0xd6, 0xec, 0xc5, 0xe0, - 0x80, 0xc1, 0x08, 0xac, 0x66, 0xf0, 0xa0, 0xb3, 0x90, 0x4e, 0xa7, 0x4e, - 0xed, 0xf6, 0xcd, 0x5f, 0xd0, 0xb6, 0x2d, 0x00, 0xfb, 0xfd, 0xfe, 0x4b, - 0x59, 0x96, 0x8f, 0x4d, 0xd3, 0xdc, 0x01, 0x4e, 0x44, 0xf2, 0x30, 0x0c, - 0x9f, 0x86, 0xc3, 0xe1, 0x6f, 0x80, 0xa0, 0x6d, 0x5b, 0x76, 0xbb, 0xdd, - 0xb7, 0xf3, 0xf9, 0xfc, 0x35, 0x4d, 0xd3, 0x5e, 0x96, 0x65, 0x78, 0xef, - 0x19, 0x0c, 0x06, 0x4c, 0xa7, 0xd3, 0x8f, 0x28, 0x8a, 0x7e, 0x4e, 0x26, - 0x93, 0xef, 0x6a, 0xbd, 0x5e, 0x3f, 0x9c, 0x4e, 0xa7, 0x1f, 0x49, 0x92, - 0xf4, 0x2e, 0x97, 0x0b, 0xdb, 0xed, 0x96, 0xe3, 0xf1, 0x88, 0x31, 0x86, - 0x2c, 0xcb, 0x42, 0x63, 0xcc, 0x7d, 0x5d, 0xd7, 0xbb, 0x1b, 0x6b, 0xed, - 0x73, 0x9a, 0xa6, 0xb7, 0x00, 0x4a, 0x29, 0x44, 0x04, 0x11, 0x41, 0x29, - 0x05, 0x40, 0x9a, 0xa6, 0xbd, 0xb2, 0x2c, 0x1f, 0xc5, 0x39, 0x67, 0xac, - 0xb5, 0x78, 0xef, 0x09, 0x82, 0x80, 0xd5, 0x6a, 0x45, 0x10, 0x04, 0xb4, - 0x6d, 0x8b, 0x73, 0x8e, 0xa2, 0x28, 0x68, 0x9a, 0xe6, 0x4e, 0x00, 0xf1, - 0xde, 0x93, 0x24, 0x09, 0x45, 0x51, 0x10, 0xc7, 0x31, 0x22, 0x42, 0x92, - 0x24, 0x68, 0xad, 0x59, 0x2e, 0x97, 0x00, 0xee, 0x46, 0x29, 0xf5, 0xde, - 0xed, 0x76, 0xb9, 0x5e, 0xaf, 0x78, 0xef, 0xa9, 0xaa, 0x8a, 0xaa, 0xaa, - 0xfe, 0x5b, 0x6b, 0x8d, 0x88, 0xe4, 0xa2, 0xb5, 0x7e, 0x99, 0xcd, 0x66, - 0x9f, 0xf2, 0x3c, 0xef, 0x59, 0x6b, 0x31, 0xc6, 0x00, 0x10, 0xc7, 0x31, - 0x9d, 0x4e, 0x87, 0xf9, 0x7c, 0xfe, 0x11, 0x86, 0xe1, 0x93, 0xda, 0x6c, - 0x36, 0x7b, 0x6b, 0x6d, 0xd8, 0xef, 0xf7, 0x3f, 0x5b, 0x6b, 0xc3, 0xba, - 0xae, 0x01, 0x30, 0xc6, 0xb0, 0x58, 0x2c, 0xfe, 0x44, 0x51, 0xf4, 0x3a, - 0x1e, 0x8f, 0xdf, 0x82, 0x7f, 0xe1, 0x87, 0xc3, 0xe1, 0xc1, 0x5a, 0xfb, - 0xec, 0x9c, 0x33, 0x80, 0x28, 0xa5, 0xde, 0xb5, 0xd6, 0x2f, 0xa3, 0xd1, - 0xe8, 0x17, 0xc0, 0x5f, 0xd1, 0x17, 0xa6, 0x12, 0x83, 0xc3, 0x30, 0x9b, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 - -}; -static unsigned int img_io_input_connector_10x10_png_len = 468; diff --git a/FL/img_io_output_connector_10x10_png.h b/FL/img_io_output_connector_10x10_png.h deleted file mode 100644 index 1a0503f..0000000 --- a/FL/img_io_output_connector_10x10_png.h +++ /dev/null @@ -1,63 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -static unsigned char img_io_output_connector_10x10_png[] = { -0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, - 0x08, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x32, 0xcf, 0xbd, 0x00, 0x00, 0x00, - 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, - 0x88, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x00, - 0x9e, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x22, 0xcb, 0xc6, 0x03, 0x00, 0x00, - 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, - 0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, - 0x00, 0x01, 0x61, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x35, 0xd0, 0xbf, - 0x6a, 0xc2, 0x40, 0x00, 0x07, 0xe0, 0xdf, 0xfd, 0x89, 0xe4, 0x32, 0xc4, - 0x40, 0xed, 0x22, 0x9c, 0x50, 0x24, 0x99, 0x1c, 0xdc, 0x33, 0x38, 0x64, - 0xec, 0x03, 0x14, 0x9c, 0xd4, 0xb9, 0x7b, 0xe9, 0x54, 0x3a, 0x95, 0xd2, - 0xb1, 0x1d, 0x74, 0xeb, 0xe4, 0xec, 0xd2, 0x31, 0x01, 0x9f, 0x40, 0x04, - 0xe9, 0x10, 0x85, 0x06, 0x1c, 0x6d, 0x40, 0x34, 0xe4, 0xd0, 0x0b, 0x5e, - 0xa7, 0x7e, 0x8f, 0xf0, 0x11, 0x63, 0x0c, 0x00, 0x60, 0xbd, 0x5e, 0xdf, - 0x96, 0x65, 0xf9, 0xa0, 0xb5, 0xbe, 0x21, 0x84, 0x54, 0x9c, 0xf3, 0x9d, - 0x10, 0xe2, 0x31, 0x08, 0x82, 0x18, 0x00, 0x88, 0x31, 0x06, 0xab, 0xd5, - 0xea, 0x69, 0xbb, 0xdd, 0xde, 0x27, 0x49, 0xd2, 0xb0, 0x6d, 0x1b, 0x8c, - 0x31, 0x14, 0x45, 0x81, 0x28, 0x8a, 0x72, 0x29, 0xe5, 0x7b, 0xa7, 0xd3, - 0x79, 0x66, 0xfd, 0x7e, 0x3f, 0xca, 0xb2, 0xec, 0x6d, 0x36, 0x9b, 0x35, - 0x84, 0x10, 0x18, 0x8d, 0x46, 0xe8, 0x76, 0xbb, 0x58, 0x2e, 0x97, 0x58, - 0x2c, 0x16, 0x4e, 0xb3, 0xd9, 0xec, 0x00, 0xf8, 0xa6, 0x4a, 0xa9, 0x97, - 0x38, 0x8e, 0xaf, 0x00, 0x40, 0x6b, 0x8d, 0xf3, 0xf9, 0x8c, 0xd3, 0xe9, - 0x04, 0xad, 0x35, 0x00, 0x20, 0x49, 0x92, 0x46, 0x59, 0x96, 0x0f, 0xbc, - 0xaa, 0xaa, 0xeb, 0xe3, 0xf1, 0x08, 0xc6, 0x18, 0x2e, 0x97, 0x0b, 0xc6, - 0xe3, 0x31, 0x8c, 0x31, 0xa0, 0x94, 0xa2, 0x56, 0xab, 0xe1, 0x70, 0x38, - 0x40, 0x6b, 0x7d, 0xc3, 0x8d, 0x31, 0x9c, 0x52, 0x8a, 0xe1, 0x70, 0x08, - 0xcf, 0xf3, 0x30, 0x9d, 0x4e, 0xa1, 0xb5, 0xc6, 0x60, 0x30, 0x40, 0x51, - 0x14, 0x98, 0x4c, 0x26, 0x20, 0x84, 0x54, 0xd4, 0xb2, 0xac, 0x1f, 0xd7, - 0x75, 0xe1, 0xba, 0x2e, 0x38, 0xe7, 0x70, 0x1c, 0x07, 0x42, 0x08, 0x30, - 0xc6, 0x60, 0xdb, 0x36, 0x3c, 0xcf, 0x03, 0xe7, 0x7c, 0x47, 0xd2, 0x34, - 0xbd, 0xdd, 0x6c, 0x36, 0x9f, 0xf3, 0xf9, 0xbc, 0x51, 0xaf, 0xd7, 0x91, - 0x65, 0x19, 0x00, 0xa0, 0xd5, 0x6a, 0x41, 0x29, 0x85, 0x30, 0x0c, 0xf3, - 0x76, 0xbb, 0x7d, 0x47, 0x7d, 0xdf, 0xff, 0x92, 0x52, 0x7e, 0xf4, 0x7a, - 0xbd, 0x3c, 0xcf, 0x73, 0xfc, 0xdb, 0xef, 0xf7, 0x08, 0xc3, 0xf0, 0x57, - 0x4a, 0xf9, 0x1e, 0x04, 0x41, 0x4c, 0xfe, 0xc3, 0xd3, 0x34, 0x8d, 0x94, - 0x52, 0x2f, 0x55, 0x55, 0x5d, 0x1b, 0x63, 0xb8, 0x65, 0x59, 0x3f, 0x8e, - 0xe3, 0xbc, 0xfa, 0xbe, 0xff, 0x05, 0x00, 0x7f, 0xb0, 0xa3, 0x9e, 0x20, - 0x9c, 0xde, 0x99, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; -static unsigned int img_io_output_connector_10x10_png_len = 484; diff --git a/FL/lib b/FL/lib deleted file mode 120000 index dc598c5..0000000 --- a/FL/lib +++ /dev/null @@ -1 +0,0 @@ -../lib \ No newline at end of file diff --git a/FL/menu_popup.C b/FL/menu_popup.C deleted file mode 100644 index afe3b95..0000000 --- a/FL/menu_popup.C +++ /dev/null @@ -1,61 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include <FL/Fl.H> -#include <FL/Fl_Menu_.H> -#include <FL/Fl_Menu_Item.H> - -/** popup menu and execute callback */ -bool -menu_popup ( Fl_Menu_ *m, int X, int Y ) -{ - const Fl_Menu_Item *r = m->menu()->popup( X, Y, m->label() ); - - if ( r ) - { - m->value( r ); - if ( r->callback() ) - r->do_callback( static_cast<Fl_Widget*>(m) ); - else if ( m->callback() ) - m->do_callback( static_cast<Fl_Widget*>(m), m->user_data() ); - - return true; - } - - return false; -} - -/** popup menu and execute callback */ -bool -menu_popup ( Fl_Menu_ *m ) -{ - return menu_popup( m, Fl::event_x(), Fl::event_y() ); -} - -/** set a single callback for all items in menu. */ -void -menu_set_callback( Fl_Menu_Item *menu, void (*callback)( Fl_Widget *, void * ), void *user_data ) -{ - for ( int i = menu->size(); i--; ) - if ( menu[i].label() && ! menu[i].submenu() ) - { - menu[i].callback( callback ); - menu[i].user_data( user_data ); - } -} diff --git a/FL/menu_popup.H b/FL/menu_popup.H deleted file mode 100644 index 67c5b78..0000000 --- a/FL/menu_popup.H +++ /dev/null @@ -1,26 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -class Fl_Menu_; -struct Fl_Menu_Item; -class Fl_Widget; - -bool menu_popup ( Fl_Menu_ *m, int X, int Y ); -bool menu_popup ( Fl_Menu_ *m ); -void menu_set_callback ( Fl_Menu_Item *menu, void (*callback)( Fl_Widget *, void * ), void *user_data ); diff --git a/FL/test_press.C b/FL/test_press.C deleted file mode 100644 index 0a79238..0000000 --- a/FL/test_press.C +++ /dev/null @@ -1,40 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Fl::test_shortcut() is broken for use in FL_PUSH handlers etc, - * because it relies on Fl::event_text(), which isn't cleared as it - * should be--and there's no official way to clear it. Therefore, we - * provide a test_press() function instead, which, unlike - * test_shortcut(), does not treat a missing FL_SHIFT as "don't care". */ - -#include <FL/Fl.H> - -int -test_press ( unsigned long e ) -{ - if ( Fl::event_text()[0] ) - ((char *)Fl::event_text())[0] = '\0'; - - const int mod_mask = FL_SHIFT | FL_ALT | FL_CTRL; - - if ( ( e & mod_mask ) != ( Fl::event_state() & mod_mask ) ) - return false; - else - return Fl::test_shortcut( e ); -} diff --git a/FL/test_press.H b/FL/test_press.H deleted file mode 100644 index 3b0fe55..0000000 --- a/FL/test_press.H +++ /dev/null @@ -1,20 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -int test_press ( unsigned long e ); diff --git a/FL/util/ntk-perf.C b/FL/util/ntk-perf.C deleted file mode 100644 index ca32236..0000000 --- a/FL/util/ntk-perf.C +++ /dev/null @@ -1,163 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include <FL/Fl.H> -#include <FL/Fl_Double_Window.H> -#include <FL/Fl_Single_Window.H> -#include <FL/Fl_Pack.H> -#include <FL/Fl_Choice.H> -#include <FL/fl_draw.H> -#include <sys/time.h> -#include <stdio.h> - -static Fl_Boxtype boxtype = FL_UP_BOX; - -#include <unistd.h> - -unsigned long long tv_to_ts ( timeval *tv ) -{ - return tv->tv_sec * 1e6 + tv->tv_usec; -} - -unsigned long long get_ts ( void ) -{ - struct timeval then; - gettimeofday( &then, NULL ); - - return tv_to_ts( &then ); -} - -class PerfTest : public Fl_Widget -{ -public: - - PerfTest ( int X, int Y, int W, int H, const char *L=0 ) : Fl_Widget( X, Y, W, H, L ) - { - align(FL_ALIGN_TOP | FL_ALIGN_RIGHT |FL_ALIGN_INSIDE); - box(FL_UP_BOX); - labelcolor( FL_WHITE ); - use_cairo = false; - } - - - bool use_cairo; - - void draw ( void ) - { - if ( use_cairo ) - fl_push_use_cairo(true); - - fl_rectf( x(), y(), w(), h(), FL_BLACK ); - - unsigned long long then = get_ts(); - - fl_push_clip( x(), y(), w(), h() ); - - int count = 400; - - /* draw stuff */ - int i = 0; - for ( ; i < count; ++i ) - fl_draw_box( boxtype, x(), y(), w(), h(), fl_lighter( FL_BLACK ) ); - - fl_pop_clip(); - - unsigned long long now = get_ts(); - - double elapsedms = (now - then) / 1000.0; - - static char text[256]; - sprintf( text, "Drew %i boxes in in %fms", i, elapsedms ); - - fl_color( FL_RED ); - fl_draw( text, x(), y(), w(), h(), FL_ALIGN_CENTER | FL_ALIGN_INSIDE ); - - draw_label(); - - if ( use_cairo ) - fl_pop_use_cairo(); - } -}; - - -void -boxtype_cb ( Fl_Widget *w, void *v ) -{ - const char *picked = ((Fl_Choice*)w)->mvalue()->label(); - - if ( !strcmp( picked, "UP_BOX" ) ) - boxtype = FL_UP_BOX; - else if ( !strcmp( picked, "FLAT_BOX" ) ) - boxtype = FL_FLAT_BOX; - else if ( !strcmp( picked, "ROUNDED_BOX" ) ) - boxtype = FL_ROUNDED_BOX; - else if ( !strcmp( picked, "OVAL_BOX" ) ) - boxtype = FL_OVAL_BOX; - - w->window()->redraw(); -} - -int -main ( int argc, char **argv ) -{ - { - Fl_Single_Window *w = new Fl_Single_Window( 800, 600 ); - - { Fl_Choice *o = new Fl_Choice( 0, 0, 200, 24, "Boxtype" ); - o->align( FL_ALIGN_RIGHT ); - - o->callback( boxtype_cb, NULL ); - - o->add( "UP_BOX" ); - o->add( "FLAT_BOX" ); - o->add( "ROUNDED_BOX" ); - o->add( "OVAL_BOX" ); - } - - { - Fl_Pack *o = new Fl_Pack( 0, 24, 800, 600 - 24 ); - o->type( 0 ); - - { - PerfTest *o = new PerfTest( 0,0, 800, 400, "Xlib" ); - } - - { - PerfTest *o = new PerfTest( 0,0, 800, 400, "Cairo" ); - o->use_cairo = true; - } - - o->end(); - } - - w->end(); - w->show(); - } - - /* { */ - /* Fl_Single_Window *w = new Fl_Single_Window( 800, 600 ); */ - - /* PerfTest *o = new PerfTest( 0,0, 800, 600 ); */ - - /* w->end(); */ - /* w->show(); */ - /* } */ - - Fl::run(); -} diff --git a/FL/wscript b/FL/wscript deleted file mode 100644 index a4056c9..0000000 --- a/FL/wscript +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python - -def options(opt): - pass - -def configure(conf): - pass - -def build(bld): - bld.stlib( - source = -''' -About_Dialog.fl -Fl_Menu_Settings.C -Fl_Scalepack.C -Fl_Text_Edit_Window.fl -Fl_Value_SliderX.C -Fl_DialX.C -Fl_SliderX.C -New_Project_Dialog.fl -event_name.C -menu_popup.C -test_press.C -focus_frame.C -''', - includes = '.', - export_incdirs = [ '.' 'FL' ], - uselib = 'PTHREAD NTK', - target = 'fl_widgets') diff --git a/README.build b/README.md similarity index 100% rename from README.build rename to README.md diff --git a/mixer/doc/MANUAL.html b/mixer/doc/MANUAL.html deleted file mode 100644 index 1c554a4..0000000 --- a/mixer/doc/MANUAL.html +++ /dev/null @@ -1,515 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head> -<meta name="generator" content="Generated by MUP v3.5"> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> -<link type="text/css" rel="stylesheet" href="mup.css"> -<title>Non Mixer User Manual - - - -
-

Non Mixer User Manual

-

-
-Jonathan Moore Liles <male@tuxfamily.org>
-
- -

-
- -

1. Non Mixer User Manual

-
- - - -
-Fig. 1.1. Mixer -
fig. 1.1
-

-The Non-Mixer is a stand-alone audio mixer, utilizing JACK as an audio subsystem. At the time of writing, the architecture of Non-Mixer is unique. By making the mixer stand-alone, concepts such as busses, sends, and inserts are eliminated, as the same goals can be achieved by simply adding more strips to the mixer. -

-

-Start by creating a new project (menu item Project/New). -

-
- - - -
-Fig. 1.2. New Project -
fig. 1.2
-

-After the project has been created. Hit a or choose Mixer/Add Strip from the menu to add a new strip to the mixer. -

-

1.1. Mixer Groups

-
- -
fig.
-

-Groups serve several purposes. Firstly, they allow for some organization of strips. Groups also allow parallel relationships of mixer strips to be made explicit. This has important performance implications in JACK2. Non Mixer supports an unlimited number of groups, each of which can contain an unlimited number of mixer strips. -

-

1.1.1. How to Choose Groupings

-

- All strips in a group should be completely parallel with no feedback loop connections. A typical group might be named 'Input' and contain all input strips (strips that accept input from Non Timeline and have outputs all connecting to some master bus). -

-

-To put it another way, if you have 100 inputs strips with identical output configurations (e.g. stereo or B-Format), that all connect to a master bus, then you have a candidate for a group. -

-

1.1.2. Considering JACK Overhead

-

-JACK provides immense flexibility. But, as in most situations, that flexibility comes with a cost. In JACK the cost is a context switch per client. This applies even for many clients which belong to the same process, as in Non Mixer. Various factors go into determining the price of a context switch on any given system. It's not very expensive, but it does add up. It becomes problematic in sessions involving many clients (think 100s), each of which having a small DSP load (often smaller than the cost of JACK's context context switch). JACK could be smart enough to recognize that some clients belong to the same process and could be executed serially without requiring a context switch, but at the time of writing neither JACK1 nor JACK2's scheduling is that smart. -

-

-If you're mixing a normal song (couple of dozen tracks) at low latency, this overhead will probably account for less than 1% of the total DSP load. If you're mixing an entire orchestra at ultra-low latency, then it might account for a quarter or more of the total DSP load. -

-

-Groups mitigate this cost by reducing the number of JACK clients required for a mix. Strips in a group will execute serially without context switches or thread synchronization--reducing the total JACK overhead. However, if you have several groups, then they may all by run in parallel by JACK2. -

-

-

-To illustrate this point here are some figures from an actual song session including the whole Non suite plus a sampler, a synth and an ambisonics convolution reverb with a total of 13 strips in 4 groups in different configurations on the same system. -

-

-JACK's DSP load figures are interpreted thus: if at a 2.7ms software latency setting the average time a proces cycle takes to complete is 2.7ms, then the DSP load is 100%. The usable ceiling on DSP load is 80%. This is true for both JACK1 and JACK2. The difference is that JACK2 may use all available CPU cores to execute the graph (if there are enough clients in parallel signal flow). -

-

-32-bit Intel Core2 Duo @1.6Ghz -r 48000 -p 256 -n 2 (5.3ms) -

-
- - - - - -
JACK VerGroupsDSP Load
JACK1N39%
JACK1Y27%
JACK2N24%
JACK2Y31%
-

-AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 256 -n 2 (5.3ms) -

-
- - - - - -
JACK VerGroupsDSP Load
JACK1N28%
JACK1Y12%
JACK2N12%
JACK2Y11%
-

-AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 128 -n 2 (2.7ms) -

-
- - - - - -
JACK VerGroupsDSP Load
JACK1N29%
JACK1Y17%
JACK2N17%
JACK2Y17%
-

-AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 32 -n 2 (0.7ms) -

-
- - - - - -
JACK VerGroupsDSP Load
JACK1Nx
JACK1Yx
JACK2N43%
JACK2Y41%
-

-As you can see, for multiprocessor systems, JACK2 clearly has an advantage even without grouping. -

-

-Of course, results will vary depending on the system and the mix. On the dual core system, performance actually degraded with JACK2 when using groups--this is because the number of parallel flows that JACK2 detected was reduced and the second core was being under utilized. Similarly, the performance of the 8-core AMD system doesn't seem that great even in the ungrouped mode--this is because the DSP load of each individual client is around the same as the cost of the context switching. It's a wash either way (if each strip had more or more complex modules on it, then the ungrouped mode would probably perform better). Since JACK1 cannot take advantage of more than 1 CPU core, there is no benefit to parallelism and grouped mode always outperforms ungrouped mode. -

-

-So, for maximum capacity the combination of a multicore CPU with JACK2 and mixer groups is best. -

-

1.1.3. Creating a New Group

-

-Groups can be created by selecting the group dropdown on any mixer strip and choosing 'New Group'. A window will popup asking for a group name. Group names must be unique. The group will then be created and the selected strip added to it. -

-

1.1.4. Adding a Strip to an Existing Group

-

-To add a strip to an existing group, simply select a group name from the group dropdown on the strip. -

-

1.1.5. Removing a Strip from a Group

-

- Select '---' from the group dropdown. The strip will be removed from the group and will run in an independent JACK client. -

-

1.1.6. Removing a Group

-

-Groups are destroyed automatically as soon as they contain zero strips. -

-

1.1.7. Monitoring Group DSP Load

-

-Above the grop dropdown on each strip is a DSP load meter for the selected group. For ungrouped strips or strips which are the only one in their group, this is simply the DSP load of the single strip. -

-

-If DSP usage goes up when strips are fed silence, then you're probably running a plugin which has denormal issues. -

-

1.2. Mixer Strips

-
- - - -
-Fig. 1.3. Mixer Strip -
fig. 1.3
-

-Each mixer strip has a name and color, each of which may be defined by the user. Names, but not colors, must be unique. In addition, each strip has controls to move it left or right (the arrows) in the display and to remove it entirely (the 'X'). -

-

-Strips start out in narrow mode, with the fader view enabled. Click the desired button to toggle the mode or view. -

-

-

-The fader view comprises a large gain control and digital peak meter indicator. These are automatically connected to the default gain and meter modules of the strip's signal chain. -

-

-To see how an audio signal traveling through this strip will be processed, switch to its signal view. -

-

1.2.1. Navigation

-

-A strip is focused when you click on it. Focus can be moved among strips with the Tab and Shift-Tab keys. -

-

1.2.2. Control

-

-The focused strip can be moved in the display order via the [ and ] keys. Delete removes a strip (with confirmation dialog). n and w set the focused strip's width to narrow or wide, respectively, and f and s switch between fader and signal views. The strip's context menu can be invoked without the mouse by hitting the Menu key (assuming your keyboard has one). -

-

1.2.3. Signal Chain

-

-The signal chain view of a mixer strip provides a way to view and manipulate the signal processing of a mixer strip. -

-

1.2.3.1. Modules

-
- - - -
-Fig. 1.4. Modules -
fig. 1.4
-

-All signal processing in Non Mixer occurs in Modules. Modules are signal processing abstractions providing ports for audio and control I/O and, in addition, some simple user interface. Sink and source modules carry audio out of and into JACK. -

-

-Modules are displayed as named blocks. Some modules (e.g. the Meter module) may have additional GUI components. -

-

-Each module has zero or more audio I/O ports and zero or more control ports. Audio routing between modules is handled automatically. Modules with mono audio configurations (one channel in, one channel out) can be automatically adjusted to support any number of discrete channels. Modules with more (related) channels, however, introduce restrictions on the order in which modules can be chained. -

-

-An indicator in the upper left-hand corner of each module block indicates whether the module has any parameters bound to controls. -

-

-Non Mixer has several built-in modules. They are: -

-
-
JACK
-
Performs JACK I/O
-
Gain
-
Applies gain in dB
-
Meter
-
Digital Peak Meter
-
Mono Pan
-
Performs intensity panning of a mono signal into a stereo signal.
-
Aux
-
Provides auxiliary outputs
-
Spatializer
-
Provides advanced Ambisonics spatialization with distance simulation.
-
Plugin
-
Hosts a LADSPA plugin
-
-
1.2.3.1.1. OSC Control
-

-The input parameters of all modules are controllable via OSC, regardless of whether the parameter is set as controllable. -

-

-The format of the automatically generated OSC path names is as follows: -

-
-
-/strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME]
-
-

-The UDP port that the OSC server binds to can be set by providing the --osc-port command-line option. Without this option, a random port will be bound automatically (the exact OSC URL will always be printed to the console as a line beginning with "OSC: "). -

-

-The default path accepts a float value between 0.0 and 1.0 (a Control Voltage like signal) which will be automatically scaled to the allowable range of the control. -

-

-A path ending in /unscaled is also available, which accepts exact values, which will be clamped to the allowable range. For example: -

-
-
-/strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME]/unscaled
-
-

-If same module/plugin is used twice in a signal chain (e.g. multiple Gain stages), then a position dependent sequence number will be appended to the module name. For example, a path might look like the following: -

-
-
-/strip/Foo/Gain.1/Gain_(dB)
-
-

-For the second instance of the Gain module on the strip named 'Foo'. -

-

-There's a possibility to get exact OSC path for module controls. For this you need to switch strip mode to 'Signl', right click a module, for example 'Gain', and open 'Edit parameters' dialog. OSC path will be shown in a statusbar of the main window when you hover a parameter. -

-

-Non-DAW accesses these same signals via a more advanced signal routing layer on top of OSC. Any module parameter is easily controlled via Control Sequences in Non-DAW without the need to specify an OSC URL. -

-
1.2.3.1.2. MIDI Control
-

-Automatic translation between MIDI and Non's OSC Signals can be achieved by adding the headless program non-midi-mapper (included in the Non-Mixer distribution) to an NSM session. -

-

-Non-MIDI-Mapper provides JACK MIDI input and output ports that can be connected to a suitable controller device. -

-

-In Non-Mixer, the Remote Control/Start Learning menu item enters learning mode in which Non Mixer can be taught which controls to associated with which MIDI messages by clicking a control in Non-Mixer and moving the desired control on the MIDI device. Remote Control/End Learning ends the learning session. -

-

-The mapping will be saved with the NSM session. -

-
1.2.3.1.3. Manipulation
-

-Left-clicking on a module brings up a Module Parameter Editor window for the selected module. -

-

-Right-clicking on a module brings up a context menu allowing you manipulate the module, as well as to pick a new module to insert before the selected one in the chain. -

-

-Middle-clicking on a module toggles its activation state (the audio signal will bypass inactive modules). -

-

-Control+Right-clicking on a module causes it to be removed from the chain (modules added by default cannot be removed). -

-

-The focused module may also be controlled via the keyboard. Menu brings up the context menu for the focused module. Space opens the module parameter editor, b toggles the bypassed state, and Delete removes the module from the chain (without confirmation!). Control-X, Control-C and Control-V, cut, copy, and paste modules, respectively. Modules may be copied within or across chain boundaries. The normal module I/O constraints also apply to pasted modules. -

-
1.2.3.1.4. Module Parameter Editor
-
- - - -
-Fig. 1.5. Module Parameter Editor -
fig. 1.5
-

-The Module Parameter Editor is used to alter the values of a module's parameters, and in addition, to bind its parameters to controls. A menu button in the upper left-hand corner allows you to select between knob, vertical slider and horizontal slider controls. -

-

-Underneath each control is a bind button. Clicking adds a new control to the chain's Controls view and binds it to the parameter in question. For simplicity, only one control at a time may be bound to a given parameter. -

-
1.2.3.1.5. Controls
-
- - - -
-Fig. 1.6. Control View -
fig. 1.6
-

-The control view of a chain groups together all of the controls bound to parameters of modules in that chain. The default mode of controls is Manual. Right click on a control to bring up a menu which will allow you to select one of the available control I/O methods to use. When Control Voltage (CV) is selected, a CV input port will be created on the containing mixer strip's JACK client. The control will now accept values from that input. A control bound and configured in this way can then be connected to the output of a Non-DAW control sequence using your favorite connection manager. -

-
- -
NOTE: -All knob and slider controls respond to mousewheel -events. Hold down the `Ctrl` key while scrolling the mousewheel to -achieve finer resolution. -
-
-
1.2.3.1.5.1. Control Voltages
-

-The control voltage concept should be familiar to anyone who has experience with analog modular synthesizers. MIDI, while having definite advantages in many respects, multiplexes control data in such a way as to make connecting one MIDI control to a parameter involve a significant inconvenience, usually requiring the adjustment of settings on both ends of the connection in order to separate the control data streams. -

-

-Control Voltages, on the other hand, provide a simple 1:1 source to sink relationship and offer much higher resolution, both in time and value, than can be natively expressed through MIDI. The chief advantage of CV in the context of Non-DAW is the ease with which an control sequence can be connected to a mixer module parameter. If you have a MIDI controller that you'd like to use to control parameters of Non-Mixer, consider jm2cv, a JACK MIDI to Control Voltage daemon which was written by Peter Nelson specifically for use with Non-Mixer. jm2cv can be acquired by: -

-
-
-git clone git://fuzzle.org/jm2cv.git
-
-
- -
NOTE: -The use of Control Signals (OSC) should be preferred for most types -of parameter automation, as LADSPA plugins are incapable of -processing Control Voltage signals at full audio resolution anyway. -
-
-
1.2.3.1.6. Spatialization
-
1.2.3.1.6.1. Spatializer Module
-
- -
fig.
-

-The Spatializer Module included with Non Mixer allows one to not only control the position of a sound source (angle and elevation), but also to control it's apparent distance from the listener. -

-

-Distance cues are based on physical properties--the speed of sound in air, the damping effect of humidity, the ratio of reverb early and late reflections, the volume of the sound. -

-

-In legacy mixers, all of these properties must be controlled individually by the engineer. This is nearly always a process of trial and error. Much of a studio engineers' skill lies in his ability to guess at these values and arrive at a reasonably realistic sounding result. -

-

-Non Mixer eliminates the guesswork and combines all of these controls into a single spatialization point encoding both a sound source's position relative to the listener and its distance. No matter where the point is placed, the result will be realistic. -

-

-Use of the Spatializer Modules eliminates much complexity from the mixing process. No more back and forth, no more guessing at values for reverb sends and predelay and EQ. The Spatializer does it all for you. -

-

-The B-Format outputs of the Spatializer Module are in the order standard order WXYZ. -

-

-All Spatializer Module instances will present controls and aziumuth, elevation, and radius. Additionally, a Highpass control is provided to compensate for the proximity effect in close-mic'd signals. The default cutoff is 200Hz. Adjust it according to the nature of the input signal. -

-

-A Spatializer Module fed stereo input will perform stereo encoding and will present a Width control. -

-1.2.3.1.6.1.1. Reverb Routing -

-The Spatializer module is intended to work with an external reverb engine having Ambisonics B-Format inputs for early reflections and a Mono input for reverb tail (and, of course, B-Format outputs). -

-
- -
fig.
-

-The Spatializer Module has two sets auxiliary outputs for reverb send. One, consisting of a single mono signal, is intended to be connected to the input of a reverb tail, otherwise known as a diffuse field. Another set of outputs in B-Format is indended to be connected to the B-Format inputs of an early reflection reverb engine. The output of the reverb engine should be 100% 'wet'. -

-

-I have crafted several jconvolver config files that meet these specifications. They can be found in ambiverb.tar.bz2 -

-

-The main outputs of the strip should go to a master bus, into which the output of the reverb engine is also fed. -

-
1.2.3.1.6.2. LADSPA Plugins
-

-There are several Ambisonics panners/encoders released as LADSPA plugins. When one of these plugins is added to a strip, Non Mixer will detect its parameter signature and create a Spatialization Control for it just as with the Spatializer Module. -

-
- - - -
-Fig. 1.7. Spatialization Control on a Strip -
fig. 1.7
-

-Whenever a module is added to a strip whose set of parameters include parameters named Azimuth and Elevation (and perhaps Radius), Non-Mixer will detect this and automatically attach a Spatializer control to these parameters. The Spatializer will be displayed at the bottom of the mixer strip. A larger version of the control may also be found in the Module Parameter Editor. -

-
- - - -
-Fig. 1.8. Spatialization Control in the Module Parameter Editor -
fig. 1.8
-

-The spatialization control may be visualized as moving the sound source across the surface of a hemispherical dome enclosing the listener. -

-

-The output of the spatializing plugin may be routed into a decoding plugin following it the same strip or, more usefully, the output of a number of Ambisonic panning plugins on different strips may be routed (through JACK) into a single master decoder instance on a final strip. -

-

1.3. Spatialization Console

-
- -
fig.
-

-The Spatialization Console allows the user to view and control all of the source positions in an Ambisonics mix at once. -

-

-The visibility of the Spatialization Console may be toggled with the F8 key. -

-

-The console will display a point for each Spatializer Module or other Ambisonics panner plugin contained in the mix. -

-

-There are two projections available, Planar and Spherical. The range of the view can be adjusted with the range dropdown in the lower lefthand corner. -

-

1.4. Projects

-

-A Non-Mixer project is a directory where Non-Mixer keeps the strip settings, project specific settings, and some meta-data. A project is completely self-contained. You can rename a project as simply as: -

-
-
-$ mv Project-A Project-B
-
-

1.4.1. JACK I/O

-

-Each mixer strip is presented as a separate JACK "client". This helps to avoid the necessity of internally duplicating JACK's routing logic and, with JACK2, permits the possibility of parallel execution of mixer strip signal chains. -

-

-The JACK client name of each strip will correspond to the name of the strip. -

-
- -
NOTE: -The JACK API makes implementing this far more difficult and kludgey than it should have to be. -Please petition your local JACK developer to accept jack_client_set_name() into the API. -
-
-
- - - -
-Fig. 1.9. Patchage -
fig. 1.9
-
- - diff --git a/mixer/doc/MANUAL.mu b/mixer/doc/MANUAL.mu deleted file mode 100644 index b4a6918..0000000 --- a/mixer/doc/MANUAL.mu +++ /dev/null @@ -1,544 +0,0 @@ - -! title Non Mixer User Manual -! author Jonathan Moore Liles #(email,male@tuxfamily.org) - --- Table Of Contents - -: Non Mixer User Manual - -/ Mixer -< non-mixer-complex.png - - The Non-Mixer is a stand-alone audio mixer, utilizing JACK as an - audio subsystem. At the time of writing, the architecture of - Non-Mixer is unique. By making the mixer stand-alone, concepts such - as busses, sends, and inserts are eliminated, as the same goals can - be achieved by simply adding more strips to the mixer. - - Start by creating a new project (menu item `Project\/New`). - -/ New Project -< new-project.png - - After the project has been created. Hit `a` or choose `Mixer\/Add - Strip` from the menu to add a new strip to the mixer. - -:: Mixer Groups - -< group-dropdown.png - - Groups serve several purposes. Firstly, they allow for some - organization of strips. Groups also allow parallel relationships of - mixer strips to be made explicit. This has important performance - implications in JACK2. Non Mixer supports an unlimited number of - groups, each of which can contain an unlimited number of mixer - strips. - -::: How to Choose Groupings - - All strips in a group should be completely parallel with no feedback - loop connections. A typical group might be named 'Input' and contain - all input strips (strips that accept input from Non Timeline and - have outputs all connecting to some master bus). - - To put it another way, if you have 100 inputs strips with identical - output configurations (e.g. stereo or B-Format), that all connect to - a master bus, then you have a candidate for a group. - -::: Considering JACK Overhead - - JACK provides immense flexibility. But, as in most situations, that - flexibility comes with a cost. In JACK the cost is a context switch - per client. This applies /even for many clients which belong to the - same process/, as in Non Mixer. Various factors go into determining - the price of a context switch on any given system. It's not very - expensive, but it does add up. It becomes problematic in sessions - involving many clients (think 100s), each of which having a small - DSP load (often smaller than the cost of JACK's context context - switch). JACK *could* be smart enough to recognize that some clients - belong to the same process and could be executed serially without - requiring a context switch, but at the time of writing neither JACK1 - nor JACK2's scheduling is that smart. - - If you're mixing a normal song (couple of dozen tracks) at low - latency, this overhead will probably account for less than 1% of the - total DSP load. If you're mixing an entire orchestra at ultra-low - latency, then it might account for a quarter or more of the total - DSP load. - - Groups mitigate this cost by reducing the number of JACK clients - required for a mix. Strips in a group will execute serially without - context switches or thread synchronization--reducing the total JACK - overhead. However, if you have several groups, then they may all by - run in parallel by JACK2. - - A mixer which uses a single JACK client (which is basically the way - everything other than Non Mixer has been designed) is not a viable - solution by this author's definition, because such a mixer cannot be - from/to any other JACK clients without introducing an extra period - of latency. - - To illustrate this point here are some figures from an actual song - session including the whole Non suite plus a sampler, a synth and an - ambisonics convolution reverb with a total of 13 strips in 4 groups - in different configurations on the same system. - - JACK's DSP load figures are interpreted thus: if at a 2.7ms software - latency setting the average time a proces cycle takes to complete is - 2.7ms, then the DSP load is 100%. The usable ceiling on DSP load is - 80%. This is true for both JACK1 and JACK2. The difference is that - JACK2 may use all available CPU cores to execute the graph (if - there are enough clients in parallel signal flow). - - 32-bit Intel Core2 Duo @1.6Ghz -r 48000 -p 256 -n 2 (5.3ms) - -[[ JACK Ver, Groups, DSP Load -[[ JACK1, N, 39% -[[ JACK1, Y, 27% -[[ JACK2, N, 24% -[[ JACK2, Y, 31% - - AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 256 -n 2 (5.3ms) - -[[ JACK Ver, Groups, DSP Load -[[ JACK1, N, 28% -[[ JACK1, Y, 12% -[[ JACK2, N, 12% -[[ JACK2, Y, 11% - - AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 128 -n 2 (2.7ms) - -[[ JACK Ver, Groups, DSP Load -[[ JACK1, N, 29% -[[ JACK1, Y, 17% -[[ JACK2, N, 17% -[[ JACK2, Y, 17% - - AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 32 -n 2 (0.7ms) - -[[ JACK Ver, Groups, DSP Load -[[ JACK1, N, x -[[ JACK1, Y, x -[[ JACK2, N, 43% -[[ JACK2, Y, 41% - - As you can see, for multiprocessor systems, JACK2 clearly has an - advantage even without grouping. - - Of course, results will vary depending on the system and the mix. On - the dual core system, performance actually degraded with JACK2 when - using groups--this is because the number of parallel flows that - JACK2 detected was reduced and the second core was being under - utilized. Similarly, the performance of the 8-core AMD system - doesn't seem that great even in the ungrouped mode--this is because - the DSP load of each individual client is around the same as the - cost of the context switching. It's a wash either way (if each strip - had more or more complex modules on it, then the ungrouped mode - would probably perform better). Since JACK1 cannot take advantage of - more than 1 CPU core, there is no benefit to parallelism and grouped - mode always outperforms ungrouped mode. - - So, for maximum capacity the combination of a multicore CPU with - JACK2 and mixer groups is best. - -# All strips in a group *MUST* have the same output configuration. All -# outputs will be mixed together by identity. That is, the 'AUX \(A\)' -# outputs of each strip will be mixed together into a single 'AUX \(A\)' -# output of the group. A strip within a group whose output -# configuration differs from the group configuration will be marked as -# invalid and will not be executed. - -::: Creating a New Group - - Groups can be created by selecting the group dropdown on any mixer - strip and choosing 'New Group'. A window will popup asking for a - group name. Group names must be unique. The group will then be - created and the selected strip added to it. - -::: Adding a Strip to an Existing Group - - To add a strip to an existing group, simply select a group name from - the group dropdown on the strip. - -::: Removing a Strip from a Group - - Select '---' from the group dropdown. The strip will be removed from - the group and will run in an independent JACK client. - -::: Removing a Group - - Groups are destroyed automatically as soon as they contain zero - strips. - -::: Monitoring Group DSP Load - - Above the grop dropdown on each strip is a DSP load meter for the - selected group. For ungrouped strips or strips which are the only - one in their group, this is simply the DSP load of the single strip. - - If DSP usage goes up when strips are fed silence, then you're - probably running a plugin which has denormal issues. - -:: Mixer Strips - -/ Mixer Strip -< single-strip.png - - Each mixer strip has a name and color, each of which may be defined - by the user. Names, but not colors, must be unique. In addition, - each strip has controls to move it left or right (the arrows) in the - display and to remove it entirely (the 'X'). - - Strips start out in /narrow/ mode, with the /fader/ view - enabled. Click the desired button to toggle the mode or view. - - Each strip has a context menu which lists the available options - and their associated key-bindings. To bring up the context menu, `Right - - The fader view comprises a large gain control and digital peak meter - indicator. These are automatically connected to the default gain and - meter modules of the strip's signal chain. - - To see how an audio signal traveling through this strip will be - processed, switch to its /signal/ view. - -::: Navigation - - A strip is focused when you click on it. Focus can be moved among - strips with the `Tab` and `Shift-Tab` keys. - -::: Control - - The focused strip can be moved in the display order via the `[` and - `]` keys. `Delete` removes a strip (with confirmation dialog). `n` - and `w` set the focused strip's width to /narrow/ or /wide/, - respectively, and `f` and `s` switch between /fader/ and /signal/ - views. The strip's context menu can be invoked without the mouse by - hitting the `Menu` key (assuming your keyboard has one). - -::: Signal Chain - - The signal chain view of a mixer strip provides a way to view and - manipulate the signal processing of a mixer strip. - -:::: Modules - -/ Modules -< modules.png - - All signal processing in Non Mixer occurs in /Modules/. Modules are - signal processing abstractions providing ports for audio and control - I\/O and, in addition, some simple user interface. Sink and source - modules carry audio out of and into JACK. - - Modules are displayed as named blocks. Some modules (e.g. the Meter - module) may have additional GUI components. - - Each module has zero or more audio I\/O ports and zero or more - control ports. Audio routing between modules is handled - automatically. Modules with mono audio configurations (one channel - in, one channel out) can be automatically adjusted to support any - number of discrete channels. Modules with more (related) channels, - however, introduce restrictions on the order in which modules can be - chained. - - An indicator in the upper left-hand corner of each module block - indicates whether the module has any parameters bound to controls. - - Non Mixer has several built-in modules. They are: - -= JACK - = Performs JACK I\/O -= Gain - = Applies gain in dB -= Meter - = Digital Peak Meter -= Mono Pan - = Performs intensity panning of a mono signal into a stereo signal. -= Aux - = Provides auxiliary outputs -= Spatializer - = Provides advanced Ambisonics spatialization with distance simulation. -= Plugin - = Hosts a LADSPA plugin - -::::: OSC Control - - The input parameters of all modules are controllable via OSC, - regardless of whether the parameter is set as controllable. - - The format of the automatically generated OSC path names is as follows: - -> /strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME] - - The UDP port that the OSC server binds to can be set by providing - the `--osc-port` command-line option. Without this option, a random - port will be bound automatically (the exact OSC URL will always be - printed to the console as a line beginning with "OSC: "). - - The default path accepts a float value between 0.0 and 1.0 (a - Control Voltage like signal) which will be automatically scaled to - the allowable range of the control. - - A path ending in \/unscaled is also available, which accepts exact values, - which will be clamped to the allowable range. For example: - -> /strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME]/unscaled - - If same module\/plugin is used twice in a signal chain - (e.g. multiple Gain stages), then a position dependent sequence - number will be appended to the module name. For example, a path - might look like the following: - -> /strip/Foo/Gain.1/Gain_(dB) - - For the second instance of the Gain module on the strip named 'Foo'. - - There's a possibility to get exact OSC path for module controls. - For this you need to switch strip mode to 'Signl', right click a - module, for example 'Gain', and open 'Edit parameters' dialog. OSC - path will be shown in a statusbar of the main window when you - hover a parameter. - - Non-DAW accesses these same signals via a more advanced signal - routing layer on top of OSC. Any module parameter is easily - controlled via Control Sequences in Non-DAW without the need to - specify an OSC URL. - - -::::: MIDI Control - - Automatic translation between MIDI and Non's OSC Signals can be - achieved by adding the headless program `non-midi-mapper` (included in the - Non-Mixer distribution) to an NSM session. - - Non-MIDI-Mapper provides JACK MIDI input and output ports that can be - connected to a suitable controller device. - - In Non-Mixer, the `Remote Control\/Start Learning` menu item enters learning - mode in which Non Mixer can be taught which controls to associated with which - MIDI messages by clicking a control in Non-Mixer and moving the desired control - on the MIDI device. `Remote Control\/End Learning` ends the learning session. - - The mapping will be saved with the NSM session. - -::::: Manipulation - - Left-clicking on a module brings up a Module Parameter Editor window - for the selected module. - - Right-clicking on a module brings up a context menu allowing you - manipulate the module, as well as to pick a new module to insert - before the selected one in the chain. - - Middle-clicking on a module toggles its activation state (the audio - signal will bypass inactive modules). - - Control+Right-clicking on a module causes it to be removed from the - chain (modules added by default cannot be removed). - - The focused module may also be controlled via the keyboard. `Menu` - brings up the context menu for the focused module. `Space` opens the - module parameter editor, `b` toggles the bypassed state, and - `Delete` removes the module from the chain (without confirmation!). - `Control-X`, `Control-C` and `Control-V`, cut, copy, and paste - modules, respectively. Modules may be copied within or across chain - boundaries. The normal module I\/O constraints also apply to pasted - modules. - -::::: Module Parameter Editor - -/ Module Parameter Editor -< module-parameter-editor.png - - The Module Parameter Editor is used to alter the values of a - module's parameters, and in addition, to bind its parameters to - controls. A menu button in the upper left-hand corner allows you to - select between knob, vertical slider and horizontal slider controls. - - Underneath each control is a bind button. Clicking adds a new - control to the chain's /Controls/ view and binds it to the parameter - in question. For simplicity, only one control at a time may be bound - to a given parameter. - -::::: Controls - -/ Control View -< controls.png - - The control view of a chain groups together all of the controls - bound to parameters of modules in that chain. The default mode of - controls is /Manual/. Right click on a control to bring up a menu - which will allow you to select one of the available control I\/O - methods to use. When /Control Voltage/ (CV) is selected, a CV input - port will be created on the containing mixer strip's JACK - client. The control will now accept values from that input. A - control bound and configured in this way can then be connected to - the output of a Non-DAW control sequence using your favorite - connection manager. - -{ NOTE: -{ All knob and slider controls respond to mousewheel -{ events. Hold down the `Ctrl` key while scrolling the mousewheel to -{ achieve finer resolution. - -:::::: Control Voltages - - The control voltage concept should be familiar to anyone who has - experience with analog modular synthesizers. MIDI, while having - definite advantages in many respects, multiplexes control data in - such a way as to make connecting one MIDI control to a parameter - involve a significant inconvenience, usually requiring the - adjustment of settings on both ends of the connection in order to - separate the control data streams. - - Control Voltages, on the other hand, provide a simple 1:1 source to - sink relationship and offer much higher resolution, both in time and - value, than can be natively expressed through MIDI. The chief - advantage of CV in the context of Non-DAW is the ease with which an - control sequence can be connected to a mixer module parameter. If - you have a MIDI controller that you'd like to use to control - parameters of Non-Mixer, consider /jm2cv/, a JACK MIDI to Control - Voltage daemon which was written by Peter Nelson specifically for - use with Non-Mixer. jm2cv can be acquired by: - -> git clone git://fuzzle.org/jm2cv.git - - -{ NOTE: -{ The use of Control Signals (OSC) should be preferred for most types -{ of parameter automation, as LADSPA plugins are incapable of -{ processing Control Voltage signals at full audio resolution anyway. - -::::: Spatialization - -:::::: Spatializer Module - -< spatializer-module.png - - The Spatializer Module included with Non Mixer allows one to not - only control the position of a sound source (angle and elevation), - but also to control it's apparent distance from the listener. - - Distance cues are based on physical properties--the speed of sound - in air, the damping effect of humidity, the ratio of reverb early and - late reflections, the volume of the sound. - - In legacy mixers, all of these properties must be controlled - individually by the engineer. This is nearly always a process of - trial and error. Much of a studio engineers' skill lies in his - ability to guess at these values and arrive at a reasonably - realistic sounding result. - - Non Mixer eliminates the guesswork and combines all of these - controls into a single spatialization point encoding both a sound - source's position relative to the listener and its distance. No - matter where the point is placed, the result will be realistic. - - Use of the Spatializer Modules eliminates much complexity from the - mixing process. No more back and forth, no more guessing at values - for reverb sends and predelay and EQ. The Spatializer does it all - for you. - - The B-Format outputs of the Spatializer Module are in the order - standard order WXYZ. - - All Spatializer Module instances will present controls and aziumuth, - elevation, and radius. Additionally, a /Highpass/ control is - provided to compensate for the proximity effect in close-mic'd - signals. The default cutoff is 200Hz. Adjust it according to the - nature of the input signal. - - A Spatializer Module fed stereo input will perform stereo encoding - and will present a /Width/ control. - -::::::: Reverb Routing - - The Spatializer module is intended to work with an external reverb - engine having Ambisonics B-Format inputs for early reflections and a - Mono input for reverb tail (and, of course, B-Format outputs). - -< reverb-routing.png - - The Spatializer Module has two sets auxiliary outputs for reverb - send. One, consisting of a single mono signal, is intended to be - connected to the input of a reverb tail, otherwise known as a - diffuse field. Another set of outputs in B-Format is indended to be - connected to the B-Format inputs of an early reflection reverb - engine. The output of the reverb engine should be 100% 'wet'. - - I have crafted several jconvolver config files that meet these - specifications. They can be found in #(url,http:\/\/non.tuxfamily.org\/ambiverb.tar.bz2,ambiverb.tar.bz2) - - The main outputs of the strip should go to a master bus, into which - the output of the reverb engine is also fed. - -:::::: LADSPA Plugins - - There are several Ambisonics panners\/encoders released as LADSPA - plugins. When one of these plugins is added to a strip, Non Mixer - will detect its parameter signature and create a Spatialization - Control for it just as with the Spatializer Module. - -/ Spatialization Control on a Strip -< spatialization-on-strip.png - - Whenever a module is added to a strip whose set of parameters - include parameters named Azimuth and Elevation (and perhaps Radius), - Non-Mixer will detect this and automatically attach a Spatializer - control to these parameters. The Spatializer will be displayed at - the bottom of the mixer strip. A larger version of the control may - also be found in the Module Parameter Editor. - -/ Spatialization Control in the Module Parameter Editor -< spatialization-in-mpe.png - - The spatialization control may be visualized as moving the sound - source across the surface of a hemispherical dome enclosing the - listener. - - The output of the spatializing plugin may be routed into a decoding - plugin following it the same strip or, more usefully, the output of - a number of Ambisonic panning plugins on different strips may be - routed (through JACK) into a single master decoder instance on a - final strip. - -:: Spatialization Console - -< spatialization-console.png - - The Spatialization Console allows the user to view and control all - of the source positions in an Ambisonics mix at once. - - The visibility of the Spatialization Console may be toggled with the `F8` key. - - The console will display a point for each Spatializer Module or - other Ambisonics panner plugin contained in the mix. - - There are two projections available, Planar and Spherical. The range - of the view can be adjusted with the range dropdown in the lower - lefthand corner. - -:: Projects - - A Non-Mixer project is a directory where Non-Mixer keeps the strip - settings, project specific settings, and some meta-data. A project - is completely self-contained. You can rename a project as simply as: - -> $ mv Project-A Project-B - -::: JACK I/O - - Each mixer strip is presented as a separate JACK "client". This - helps to avoid the necessity of internally duplicating JACK's - routing logic and, with JACK2, permits the possibility of parallel - execution of mixer strip signal chains. - - The JACK client name of each strip will correspond to the name of the strip. - -{ NOTE: -{ The JACK API makes implementing this far more difficult and kludgey than it should have to be. -{ Please petition your local JACK developer to accept jack_client_set_name() into the API. - -/ Patchage -< non-mixer-and-non-daw-in-patchage.png diff --git a/mixer/doc/Makefile b/mixer/doc/Makefile deleted file mode 100644 index d214bab..0000000 --- a/mixer/doc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -SRCS=$(wildcard *.mu) - -OBJS=$(SRCS:.mu=.html) - -%.html: %.mu - @ echo Mupping $<... - @ mup.wrapper html $< - -.PHONY: all clean - -all: $(OBJS) - -upload: all - @ rsync -L mup.css MANUAL.html *.png ssh.tuxfamily.org:/home/non/non-mixer.tuxfamily.org-web/htdocs - -install: - @ install -d "$(DESTDIR)$(DOCUMENT_PATH)"/non-mixer - @ cp $(OBJS) *.png mup.css ../../COPYING "$(DESTDIR)$(DOCUMENT_PATH)"/non-mixer -# @ ln -sf $(PIXMAP_PATH)/logo.png $(DOCUMENT_PATH) - -clean: - rm -f $(OBJS) diff --git a/mixer/doc/controls.png b/mixer/doc/controls.png deleted file mode 100644 index aeaaa36..0000000 Binary files a/mixer/doc/controls.png and /dev/null differ diff --git a/mixer/doc/group-dropdown.png b/mixer/doc/group-dropdown.png deleted file mode 100644 index b9f4665..0000000 Binary files a/mixer/doc/group-dropdown.png and /dev/null differ diff --git a/mixer/doc/icon.png b/mixer/doc/icon.png deleted file mode 120000 index 8dca7d4..0000000 --- a/mixer/doc/icon.png +++ /dev/null @@ -1 +0,0 @@ -../icons/hicolor/256x256/apps/non-mixer.png \ No newline at end of file diff --git a/mixer/doc/mixer-strips.png b/mixer/doc/mixer-strips.png deleted file mode 100644 index baea8ca..0000000 Binary files a/mixer/doc/mixer-strips.png and /dev/null differ diff --git a/mixer/doc/modules.png b/mixer/doc/modules.png deleted file mode 100644 index 417a278..0000000 Binary files a/mixer/doc/modules.png and /dev/null differ diff --git a/mixer/doc/mup.css b/mixer/doc/mup.css deleted file mode 100644 index 10aceae..0000000 --- a/mixer/doc/mup.css +++ /dev/null @@ -1,461 +0,0 @@ - -/* Example CSS Style for MUP */ - -body -{ - font: normal normal 14pt "Helvetica", sans-serif; -/* background: url("http://non.tuxfamily.org/background-pattern.png") fixed; */ - background-color: #121212; color: lightgray; padding: 0; margin: 0; -} - -a:link { - color: white; -} -a:visited { - color: olive; -} -a:active { - color: white; -} -a:link:hover { - text-decoration: underline; -} - -/* #(url) */ -a.ext:link { - color: red; - text-decoration: none; - border-bottom: dashed silver 1; -} -a.ext:visited { - color: darkred; - border-bottom: dashed silver 1; - text-decoration: none; -} - -/* #(ref) */ -a.int:link { - border-bottom: dashed silver 0.15em; -} -a.int:link:hover { - text-decoration: none; - color: white; -} - -/* - a[href^="#"]:link { - border-bottom: dashed silver 0.15em; - } - a[href^="#"]:link:hover { - text-decoration: none; - color: white; - } - */ - -p:contains("Warning:") { - background: #d00; - color: white; - border: dotted gray 0.5em; - display: block; -} - -/* First letter of first paragraph of every chapter */ -/* - h1 + p:first-letter { - text-transform: uppercase; - float: left; - line-height: 0.8em; - font-size: 350%; - font-family: Serif; - letter-spacing: 0; - margin-right: 0.1em; - margin-top: 0.1em; - border: solid gray 1px; - padding: 1px; - color: #d00; - text-shadow: #666 3px 3px 3px; - } - */ -/* First paragraph of every chapter */ -/* - h1 + p { - text-indent: 0; - } - */ - -/* cover */ -#cover * { - background: transparent; -} -#cover { - position: relative; -/* background: #da0;*/ - background: #555; - color: #aaa; - text-align: center; - margin: 0; - padding: 0.5em; - border-top: 4px solid black; - border-bottom: 4px solid black; -} -#cover h1, #cover h3 { - text-shadow: #222 0.2em 0.2em 0.2em; - color: white; - border: none; - letter-spacing: 0.2em; - line-height: 0.8em; - margin-left: 2em; - margin-right: 2em; -} -#cover h1:before, #cover h1:after { -/* content: "::"; */ - font-size: 300%; - color: black; -} -#cover h1:before { - position: absolute; - top: 0.2em; - left: 0.1em; -} -#cover h1:after { - position: absolute; - top: 0.2em; - right: 0.1em; -} -#cover hr { - display: none; -} - -hr:first-child { - display: none; -} - -hr { - height: 0.2em; - background: #555; - color: #555; - margin-left: 0.5em; -} - -#cover a:visited { - color: black; -} - -/* endnote */ -#endnote { - color: black; -} - -/* TOC */ -#toc { - position: relative; -} -#toc hr { -} -#toc h1 { -} -#toc ul { - font-size: 125%; - font-weight: bold; - margin-bottom: 1em; -} -#toc ul ul { - font-size: 90%; - font-weight: normal; - margin-bottom: 0; -} -#toc li { - list-style: none; - -} -#toc a:link { - border-bottom: 0; -} - -/* */ -#body { - position: relative; - margin: 0 auto; - padding: 0.5em; - max-width: 900px; - background-color: #1c1c1c; -} -/* ;, : */ -h1 { - color: #fff; - border-bottom: solid #444 0.1em; - text-shadow: 1px 1px 2px #000; - -} -/* ::, :::, ::::, :::::, :::::: */ -h2, h3, h4, h5, h6 { - color: #fff; - text-shadow: 1px 1px 2px #000; - -} - -/* tables, figures */ -.fig caption { - color: gray; - text-align: center; - /* Required for Mozilla */ - margin: auto; -} -.fig table { - border: none; - margin: auto; -/* border-collapse: collapse; */ -} -/* / */ -.fig.table th { - border: none; - background: gray; - color: black; -} -/* [ */ -.fig.table td { - border: none; - background: silver; - color: black; - padding-left: 1em; - padding-right: 1em; - padding-top: 0.2em; - padding-bottom: 0.2em; -} -/* < */ - -.fig.image table { - border: none; - background: transparent; - max-width: 100%; -} -.fig.image tr, .fig.image td { - border: none; - background: transparent; - padding: 0; -} - -.fig.image img -{ - max-width: 900px; -} - -/* */ -p { - margin-right: 2%; - text-align: justify; - text-indent: 1em; -} -/* > */ -.example * -{ - background: transparent; -} -.example table -{ - margin: 0; - padding: 0; - table-layout: fixed; - width: 100%; - caption-side: top; - overflow: auto; -} -.example caption -{ - caption-side: top; - -} -.example { -} -.example p { - display: inline; - margin: 0; - padding: 0; - text-align: center; -} -.example pre { - margin-top: 0; - font-family: Monospace; - padding: 1em; - border: solid 1px black; - background: #222; - color: white; - display: block; - overflow: auto; - /* Every browser should support border radii */ -/* -moz-border-radius: 0.5em; - border-radius: 0.5em; */ -} -/* " */ -/* - .quote:before { - float: left; - font-size: 500%; - content: "\201C"; - } - */ -/* - blockquote:after { - content: "\201D"; - }*/ -.quote blockquote { - padding: 0.5em; - margin-left: 0.5em; - font-family: Serif; - border-left: solid 0.4em gray; - /* background: #333; */ - color: white; -} -/* ^ */ -small { -/* - color: silver; - font-size: 50%; - */ -} -.footnote p { - color: silver; - margin: 0; -} - -/* Popup footnotes */ -.footnote p { - display: none; -} -.footnote p:target { - display: block; - overflow: auto; - position: fixed; - left: auto; - bottom: 0; - right: 0; - max-width: 50%; - border: solid 0.3em white; - -moz-border-radius: 0.5em; - background: black; - padding: 0.2em; -} - -/* { */ -.admonition * { - background: transparent; - color: white; -} -.admonition dl -{ - display: table; - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition dt -{ - display: table-cell; - vertical-align: center; - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} -.admonition dd -{ - padding-left: 0.4em; - display: table-cell; - width: 100%; - text-align: justify; -} - -.admonition table -{ - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition td { - width: 100%; - text-align: justify; -} -.admonition td:first-child:contains("Warning:") { - background: #900; -} -.admonition td:first-child:contains("Caution:") { - background: #960; -} -.admonition td:first-child:contains("Note:") { - background: #690; -} -.admonition td:first-child { - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} - - -/* #(b) */ -/* b { color: olive; } */ -/* #(c) */ -tt { - color: #7f0; -} -/* ! keywords ... */ -p em { - color: gray; - font-style: normal; - font-weight: bold; -} - -/* *, + */ -/* Bullet, numbe */ -li { - color: #f0f; -} -/* Text */ -li span, li p { - color: white; -} -li p { - color: red; - display: block; -} -ul { - list-style-type: square; -} -dl { - margin-left: 2%; - margin-top: 1em; -} -/* = */ -dt { - background: #181818; - padding: 0.2em; - font-variant: small-caps; - font-weight: bold; - color: #f0f; -} -dd { - color: white; - text-align: justify; - margin-right: 5%; -} -dt a:link, dt a:visited { - color: #f0f; -} -dt a:link:hover { - color: silver; - text-decoration: underline; -} diff --git a/mixer/doc/new-project.png b/mixer/doc/new-project.png deleted file mode 100644 index 114fdff..0000000 Binary files a/mixer/doc/new-project.png and /dev/null differ diff --git a/mixer/doc/non-mixer-and-non-daw-in-patchage.png b/mixer/doc/non-mixer-and-non-daw-in-patchage.png deleted file mode 100644 index a2f6f32..0000000 Binary files a/mixer/doc/non-mixer-and-non-daw-in-patchage.png and /dev/null differ diff --git a/mixer/doc/non-mixer-complex.png b/mixer/doc/non-mixer-complex.png deleted file mode 100644 index 081d563..0000000 Binary files a/mixer/doc/non-mixer-complex.png and /dev/null differ diff --git a/mixer/doc/single-strip.png b/mixer/doc/single-strip.png deleted file mode 100644 index 070f825..0000000 Binary files a/mixer/doc/single-strip.png and /dev/null differ diff --git a/mixer/doc/spatialization-console.png b/mixer/doc/spatialization-console.png deleted file mode 100644 index c7baf4e..0000000 Binary files a/mixer/doc/spatialization-console.png and /dev/null differ diff --git a/mixer/doc/spatialization-in-mpe.png b/mixer/doc/spatialization-in-mpe.png deleted file mode 100644 index ca6db1f..0000000 Binary files a/mixer/doc/spatialization-in-mpe.png and /dev/null differ diff --git a/mixer/doc/spatialization-on-strip.png b/mixer/doc/spatialization-on-strip.png deleted file mode 100644 index 4c79d11..0000000 Binary files a/mixer/doc/spatialization-on-strip.png and /dev/null differ diff --git a/mixer/doc/spatializer-module.png b/mixer/doc/spatializer-module.png deleted file mode 100644 index 2c97ea0..0000000 Binary files a/mixer/doc/spatializer-module.png and /dev/null differ diff --git a/mixer/icons/hicolor/128x128/apps/non-mixer.png b/mixer/icons/hicolor/128x128/apps/non-mixer.png deleted file mode 100644 index 1965a23..0000000 Binary files a/mixer/icons/hicolor/128x128/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/16x16/apps/non-mixer.png b/mixer/icons/hicolor/16x16/apps/non-mixer.png deleted file mode 100644 index 80c147f..0000000 Binary files a/mixer/icons/hicolor/16x16/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/192x192/apps/non-mixer.png b/mixer/icons/hicolor/192x192/apps/non-mixer.png deleted file mode 100644 index e2105b1..0000000 Binary files a/mixer/icons/hicolor/192x192/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/256x256/apps/non-mixer.png b/mixer/icons/hicolor/256x256/apps/non-mixer.png deleted file mode 100644 index 5803329..0000000 Binary files a/mixer/icons/hicolor/256x256/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/32x32/apps/non-mixer.png b/mixer/icons/hicolor/32x32/apps/non-mixer.png deleted file mode 100644 index b8e44b3..0000000 Binary files a/mixer/icons/hicolor/32x32/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/36x36/apps/non-mixer.png b/mixer/icons/hicolor/36x36/apps/non-mixer.png deleted file mode 100644 index 0a1dac8..0000000 Binary files a/mixer/icons/hicolor/36x36/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/48x48/apps/non-mixer.png b/mixer/icons/hicolor/48x48/apps/non-mixer.png deleted file mode 100644 index 6230c1f..0000000 Binary files a/mixer/icons/hicolor/48x48/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/512x512/apps/non-mixer.png b/mixer/icons/hicolor/512x512/apps/non-mixer.png deleted file mode 100644 index 4d7dc6e..0000000 Binary files a/mixer/icons/hicolor/512x512/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/64x64/apps/non-mixer.png b/mixer/icons/hicolor/64x64/apps/non-mixer.png deleted file mode 100644 index 24ec27d..0000000 Binary files a/mixer/icons/hicolor/64x64/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/72x72/apps/non-mixer.png b/mixer/icons/hicolor/72x72/apps/non-mixer.png deleted file mode 100644 index 11c6e3c..0000000 Binary files a/mixer/icons/hicolor/72x72/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/96x96/apps/non-mixer.png b/mixer/icons/hicolor/96x96/apps/non-mixer.png deleted file mode 100644 index 2b7a8db..0000000 Binary files a/mixer/icons/hicolor/96x96/apps/non-mixer.png and /dev/null differ diff --git a/mixer/icons/hicolor/scalable/apps/non-mixer.svg b/mixer/icons/hicolor/scalable/apps/non-mixer.svg deleted file mode 100644 index 8b251a5..0000000 --- a/mixer/icons/hicolor/scalable/apps/non-mixer.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mixer/icons/icon-16x16.xpm b/mixer/icons/icon-16x16.xpm deleted file mode 100644 index 9062fa1..0000000 --- a/mixer/icons/icon-16x16.xpm +++ /dev/null @@ -1,774 +0,0 @@ -/* XPM */ -static char *icon_16x16[] = { -/* columns rows colors chars-per-pixel */ -"512 512 256 2 ", -" c #000201B10001", -". c #05970A5D04FE", -"X c #08080B610707", -"o c #09F70C1F09F7", -"O c #05E1106A044B", -"+ c #08271144066D", -"@ c #08B31B1B05B0", -"# c #0CEC119F0C59", -"$ c #0C651B8009E8", -"% c #105919620E7C", -"& c #12E714E912E7", -"* c #169019791650", -"= c #18181D1D1717", -"- c #1B061D321AF0", -"; c #0D4623CE09A6", -": c #11B324240E88", -"> c #11832BD60D46", -", c #0E6432DD0934", -"< c #12EA32D40DAF", -"1 c #132F3E260C6C", -"2 c #17172704144E", -"3 c #1E4C22501DCB", -"4 c #173D37C611F5", -"5 c #1A5C3D4F14A3", -"6 c #1E543E2318F0", -"7 c #20A129FF1E49", -"8 c #20A137571C9C", -"9 c #21B523D621A5", -"0 c #24C229EF239A", -"q c #2B8A2D8C2B8A", -"w c #295C38D225F3", -"e c #2E2A30642E0E", -"r c #30B13ABB2E2E", -"t c #327E34A63258", -"y c #372E393E3729", -"u c #3ABB3BF33ABB", -"i c #157545C60DCE", -"p c #187F59590EA8", -"a c #1B824832142A", -"s c #1BE555301301", -"d c #224A48481BCD", -"f c #255E5A131CD6", -"g c #1E5E62621394", -"h c #1D4B6CBE1150", -"j c #1F1F75751212", -"k c #2558688D1A8F", -"l c #25D469BB1AE1", -"z c #23687EC3157C", -"x c #26B57A1B19BB", -"c c #2A9C467F257B", -"v c #318742982D83", -"b c #2A185874222B", -"n c #378D42423434", -"m c #3F2B404E3F0E", -"M c #3A65555534DF", -"N c #2C9364312309", -"B c #2BD66ACE21BE", -"V c #331969D02976", -"C c #369D76762BF9", -"Z c #395977772ECF", -"A c #41A853863CD6", -"S c #434368BE3B91", -"D c #443A453B443A", -"F c #479D4AF54545", -"G c #4C2D4D334C25", -"H c #494954AA45F0", -"J c #525255554F4F", -"K c #543155325431", -"L c #572C592E5681", -"P c #5B655C665B65", -"I c #4A4A6666446F", -"U c #515171C74A75", -"Y c #5AD165795743", -"T c #59DA777752D2", -"R c #616177775ADB", -"E c #61AA62AB61AA", -"W c #676768686767", -"Q c #6B786C796B78", -"! c #6AA576ED6603", -"~ c #732D742E732D", -"^ c #777778787777", -"/ c #7B207C217B20", -"( c #2B3C8BF21C61", -") c #287E95EB176D", -"_ c #2B8F93BE1B9C", -"` c #30309D9D1F1F", -"' c #2E6EA7D71BAC", -"] c #3123ABAB1E3B", -"[ c #32B3BB3B1D1D", -"{ c #36B786DC298D", -"} c #336293AA23DE", -"| c #345F9C0D23CE", -" . c #3A9E93A12C1E", -".. c #3B9890792DB9", -"X. c #39709A192A18", -"o. c #36B7A7EC249C", -"O. c #34F5AD8D226D", -"+. c #3C9BA4CD2BDB", -"@. c #3CD8AD762AC6", -"#. c #3AB1B7F226EC", -"$. c #4225876A3619", -"%. c #45459A9A36D2", -"&. c #40A0ACAC2F0F", -"*. c #4096B7612D83", -"=. c #4406A2F0340D", -"-. c #44AEAE53336F", -";. c #4747A4A43838", -":. c #4B5AA4493C00", -">. c #4BE9AD513B70", -",. c #47D1B82E35BF", -"<. c #34DFC51A1EC9", -"1. c #22C0FBFB02B4", -"2. c #2727FBFB0808", -"3. c #2B2BFBFB0C45", -"4. c #2EAFFBFB1090", -"5. c #3252FBFB1454", -"6. c #35F6FBFB18D9", -"7. c #3A5AFBFB1CBD", -"8. c #3A69C8992481", -"9. c #3B89D4162424", -"0. c #3EBFD6152767", -"q. c #3E0BE84E248B", -"w. c #3E3EFBFB2121", -"e. c #42E6D43A2C36", -"r. c #449ADD322C82", -"t. c #4A1FC6303621", -"y. c #4A03D44533D0", -"u. c #4B34D6323506", -"i. c #5252D4693D3D", -"p. c #4242F47326A7", -"a. c #4174FBFB24CD", -"s. c #45C5FBFA29A9", -"d. c #4915FBFA2DC6", -"f. c #4B26E60A32A0", -"g. c #4CC3E94B340C", -"h. c #4C19F58E3198", -"j. c #4DADFBFA32B2", -"k. c #5191FBFB36B6", -"l. c #5353F3B33939", -"z. c #55B5FBFB3AFA", -"x. c #58D8FBFB3EBE", -"c. c #4E4A9791413F", -"v. c #4EE899CC420F", -"b. c #552A91BC499F", -"n. c #5D7D888854B4", -"m. c #63A390105A5A", -"M. c #5401A30946B7", -"N. c #5322AD994374", -"B. c #5535AC0B4686", -"V. c #5833ABBD49DC", -"C. c #593EB7304920", -"Z. c #66CDA9425A5A", -"A. c #6CED878765A5", -"S. c #718892636923", -"D. c #7DD3852F7A24", -"F. c #7B3B98987373", -"G. c #7733AE5D6BE5", -"H. c #57E3C80D44E8", -"J. c #5AA6D4CC467B", -"K. c #6161D38A4DE0", -"L. c #6819CF095656", -"P. c #68A2D4FD561C", -"I. c #5ABAE70643E4", -"U. c #5E08F59F459B", -"Y. c #5C8DFBFB4300", -"T. c #6060FBFB4747", -"R. c #63B9F4F44BF6", -"E. c #6449FBFB4BCA", -"W. c #6A25EAEA5499", -"Q. c #6A95F2F2537E", -"!. c #6BCDFBFB53B5", -"~. c #73DAF55B5D5D", -"^. c #7308FBFB5BA3", -"/. c #7E7EC3C37070", -"(. c #774FE836639E", -"). c #7A7AF4F4653A", -"_. c #7777FBFA60B6", -"`. c #7AFDFBFA64E7", -"'. c #7EBEFBFA696A", -"]. c #848498987D7D", -"[. c #8517AFAF7B7B", -"{. c #8767CACA7999", -"}. c #83AFFBFB6DF6", -"|. c #8F8FE4637DFE", -" X c #86C6FBFB71B1", -".X c #8A8AFBFB7575", -"XX c #8DF4FC2E79E0", -"oX c #91BCFCFC7DFE", -"OX c #83B084B183B0", -"+X c #878788888787", -"@X c #8B198C1A8B19", -"#X c #8D5A93C68ABD", -"$X c #909098988A8A", -"%X c #94A495A594A4", -"&X c #9B5D9C5E9B5D", -"*X c #9292B1A189A9", -"=X c #9D1DA5249999", -"-X c #A2A2B2329B5B", -";X c #A3C1A4C2A3C1", -":X c #A7A7A8A8A7A7", -">X c #AC53ACD4AC53", -",X c #AE6EBABAA767", -"XbXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXD.+ W bXKXKXnX~ # %XnXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXcX:X~ y . y / >XbXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX+Xo L cXKXKXnXOX+ X OXnXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX>X^ y . . . . . ", -" . . & / bXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX:X. #XKXKXKXKXKXKX#X % xXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxXP O # ~ cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXX ;XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXX. . . . . ", -" . . @XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXu & nXKXKXKXKXKXKXbX& G KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXP . ^ KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXJ # cXKXKXKXKXKXKXKX9 u KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXQ W KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXW . xXKXKXKXKXKXKXKXt 0 KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXOX . . . ", -" . D KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXOX G KXKXKXKXKXKXF @XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX- r KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX%X u nXKXKXKXKXKXL ^ KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXnX0 9 nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX:X e bXKXKXKXKXKXW E KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXy . . . ", -" . . # cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXnXxX:XJ t ;XnXnX;Xq P 1XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX;X O xXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX>XP q &XnXnX:Xy G XD m >XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX. . ", -" . . . . Q KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbXOXD - X & 0 L &XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXr L KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXnX+XG - . . * 9 J %XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXG D KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX#XG 9 & 9 G @XnXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXP . . ", -". . cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX%X# . . 3 :XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX;X 1XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX;X= = &XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX>X9 . & +XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX . . ", -" . . . G KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX~ . . @XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX- t KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX+X . . ^ KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXt 0 KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX%X. . W KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXF ", -" . . . %XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX&X . O X. ;XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX~ E KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX1X# @XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX+X . . ", -" . xXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX3 q KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX&X X =XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXD . o nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX . . . ", -" . . . . = KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX:X . X . . %XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX& KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX% >XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX0 . . . . . ", -" . . . cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX=X . . . ;XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX>X nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX0 . % nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX >XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX ~ KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXcX . . ", -" . . . . &XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXW . . E KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX~ ;XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX&X . #XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX;X ~ KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX#X . y KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX&X . ", -" . . . Y KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXq . . . q KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXy ! KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXE E KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXE r KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXK . # nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXP . . ", -" . . . . X nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX>X . >XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX1X - KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX/ O Q KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX= . X . . ", -" . . . . . 3 cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX1X# 3 cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX>X D KXKXKXKXKXKXKXKXW +XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXcX3 X 1XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXcX* . @XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX- ", -" . . . e nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX* . & xXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxX- 0 cXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX Q KXKXKXKXKXKXKXKX%X X& . . % Xt . 3 +XnXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX3 . 1XKXKXKXKXKXKX>X. 3 nXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXbX~ & . r :XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX1Xm . . - @XnXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXxXF . . . ", -" . . t D.xXKXKXKXKXKXKXKXKXKXnX>X~ 9 . . . 3 Q XnXKXKXKXKXKXKXKXKXKX1X+Xy . . ", -" . & y K E Q Q P G 9 . . . . # t G E Q Q E G q . . . e D P W Q Q Q Q Q Q Q Q Q Q Q Q ! Q Q Q Q Q Q Q Q Q Q Q Q Q Q W D X y E E 0 # D W Q Q Q Q Q Q Q Q Q Q Q Q Q Q W Q Q Q Q Q ! Q Q Q Q Q Q Q L F r # t G E Q Q E G q X . . . # 0 F P Q W W J e o . . . . . ", -" . . . . . . . . ", -" . . . . . . . . . ", -" . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . . . . . ", -" . . . . . . . . . . . . . ", -"H . . . . . . . . . . . . . . . . H ", -"UXvXK . . . . . . . . . . . . . . . . . . . . . . . . J vXUX", -"UXUXUXxXH . . . . . . . . . . . . . . . . . H xXUXUXUX", -"UXUXIXIXUX1Xn . . . . . . . . . . . . . . . . . . m 1XUXUXUXUXUX", -"UXUXUXUXUXUXUX,Xt . . . . . . . . . . . . . . . . . t ,XUXUXUXUXUXUXUX", -"UXUXUXUXUXUXUXUXUX,Xr . . . . . . . . . . . . . . . . e ,XUXUXUXUXUXUXUXUXUX", -"UXUXUXUXIXUXUXUXUXUXIX=X0 . . . . . . . . . . . . . . . . . . w -XIXIXIXUXUXUXUXIXUXIXIX", -"UXIXIXIXIXUXIXIXIXUXIXIXIX=X9 . . . . . . . . . . . . . . . . . 9 =XPXUXIXIXIXUXUXIXIXIXIXUXIX", -"IXIXIXIXIXIXIXIXIXIXIXIXIXIXPX$X3 . . . . . . . . . . . . . . . . . = $XLXIXIXIXIXIXIXIXIXIXIXIXIXIXIX", -"IXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXPX$X= . . . . . . . . . . * $XPXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIX", -"PXIXPXIXIXIXIXIXIXPXIXIXPXIXIXPXPXIXDXD.% . . . . . . . . . . . . . . . . . . . . . . . % D.DXIXPXIXIXIXIXPXIXIXIXPXIXIXIXPXIXIXIX", -"IXPXIXPXIXJXIXIXIXPXPXPXIXPXIXPXPXIXIXPXDX].o . . . . . . . . . . . . . . . . . # D.DXIXIXIXPXIXPXPXPXIXPXPXPXPXPXPXIXPXIXPXPX", -"JXPXIXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXIXAX! + . . . . . . . . . . . . . . . . . . X ~ AXLXLXPXPXPXIXIXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPX", -"PXPXPXJXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXLXLXPXAX! O . . . . . . . . . . . . X ! AXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPX", -"PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXvXY . . . . . . . . . . . . . . . . . . . . . . Y vXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPX", -"PXPXJXPXPXPXJXPXPXPXJXPXPXPXJXPXPXPXJXPXPXPXPXPXPXPXPXPXvXL . . . . . . . . . . . . . R vXPXJXPXPXJXPXPXPXJXPXPXPXJXPXJXPXPXPXPXJXPXJXPXPXJXPXPXPX", -"JXJXPXPXJXJXJXPXJXJXPXPXJXJXJXPXJXJXPXJXJXPXJXJXJXPXJXPXJXPXgXH . . . . . . . . . . . J gXPXJXJXPXPXJXJXPXPXJXPXJXPXJXJXJXPXJXPXJXPXPXPXJXPXPXJXJXPXJX", -"JXJXJXJXPXJXPXJXJXJXJXJXPXJXPXJXJXPXJXJXJXPXJXPXJXJXJXJXJXJXJXPXuXD . . . . . . . . . . . . . . . . . . . F 1XJXJXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXJXJXJXJXJXJXJXJXPXJXJX", -"PXJXJXJXJXJXJXJXPXJXJXJXJXJXJXJXJXJXPXJXJXJXJXJXPXJXJXJXPXJXJXJXPXJXuXn . . . . . . . . . . . . . . m uXJXJXJXJXJXJXJXJXPXJXJXJXPXJXPXJXJXJXJXJXPXJXPXJXJXJXJXJXJXJXJXJXJXPX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX,Xr . . . . . . . . . . . . . . . . . . r ,XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"HXJXJXJXJXJXJXJXJXJXHXPXJXJXHXJXJXJXHXJXJXHXJXJXJXHXJXJXJXJXJXJXPXHXJXJXJXHX,Xq . . . . . . . . . . . . . . e ,XHXJXJXJXJXJXJXHXJXJXJXJXJXHXHXJXHXPXJXJXJXJXJXJXHXJXJXJXHXJXJXHXJXJXJXJXHXJX", -"HXJXHXHXHXHXHXJXHXHXJXHXHXHXJXJXHXJXJXHXJXHXHXJXHXJXHXJXHXHXHXHXHXJXHXJXHXJXJXHX=X7 . . . . . . . . . . . . . . . . . . 7 -XHXHXHXHXJXHXHXHXHXJXHXHXHXJXHXJXJXJXHXHXHXHXHXHXHXJXJXHXJXHXJXHXHXJXHXJXHXJXJXHX", -"JXHXHXJXJXHXHXHXJXHXPXHXHXJXJXHXHXJXHXJXJXJXJXHXJXJXHXHXJXJXJXHXJXHXHXPXJXJXHXHXHXHX-X3 . . . . . . . . . . . . . . 3 -XGXHXHXPXHXJXHXJXJXJXJXHXHXJXHXJXHXHXHXJXPXHXHXJXHXHXHXJXHXJXHXJXHXHXJXJXHXHXJXHXHXJX", -"JXHXHXJXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXSX#X3 . . . . . . . . . . . . 2 $XSXJXHXHXJXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXJXHXJXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXFX#X* . . . . . . . . . . . . . . . * #XFXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXFXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXFXHXHXFXHXHXHXHXHXHXHXHXHXHXAXF.# . . . . . . . . . . . . . . . # D.AXHXHXFXGXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXAXD.# . . . . . . . . . . . . . . . . . # D.AXHXFXFXHXHXFXHXHXHXHXHXHXHXHXHXHXFXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXFXHXHXHXHXHXHXHXHXHXHXFX", -"HXHXHXHXHXHXHXFXHXHXFXHXHXFXHXFXHXHXHXFXHXFXFXHXFXHXHXFXFXHXFXHXHXFXHXFXHXFXFXHXHXHXGXHXFXHXFXFXSXHXFXmX! + . . . . . . . . . . . . # ! mXFXFXHXFXHXHXFXHXHXHXHXFXHXFXHXFXFXHXHXHXHXHXHXHXHXHXFXHXHXFXHXHXFXHXHXFXHXFXHXHXFXHXHXHXFXHXHXFXHXFXHX", -"HXFXHXFXHXHXFXHXFXFXFXFXHXFXHXHXFXHXHXHXHXFXFXHXHXFXHXFXHXFXHXFXHXFXHXHXFXHXFXHXHXHXHXFXFXHXHXFXHXHXHXHXHXmX! . . . . . . . . . . . . . X ! mXSXHXHXFXHXHXHXFXHXHXFXHXHXFXFXHXFXFXHXFXFXFXHXFXHXHXHXFXHXFXHXFXHXHXFXHXFXFXHXHXHXHXFXFXFXFXHXHXFXHXHXFXHX", -"FXFXFXHXFXFXFXFXFXFXFXHXHXFXFXFXFXFXFXFXFXHXFXFXFXFXFXHXFXFXHXFXFXFXFXFXFXFXHXFXFXFXFXHXFXFXFXFXFXFXSXHXSXHXGXhXY . . . . . . . . . . . . . . . . . Y gXHXFXHXFXHXFXFXFXFXFXFXFXFXFXFXFXHXFXFXHXFXFXHXFXFXHXFXFXFXFXFXHXFXFXFXFXFXFXHXFXFXFXFXFXHXFXFXFXFXFXHXFXFXFXFX", -"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXHXSXHXSXFXgXP o . . . . . . . . . . . . . . . . . . . X Y gXFXSXHXSXHXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX", -"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXSXHXSXHXFXFXHXuXJ . . . . . . . . . . . H uXHXSXHXHXSXHXSXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX", -"FXFXSXFXFXFXFXFXFXFXSXFXFXFXSXFXFXFXFXFXFXFXFXFXSXFXFXFXFXFXSXFXFXSXFXFXFXFXSXFXSXFXFXFXFXFXFXFXFXFXFXSXFXHXSXFXFXFXFXFXSXuXD o . . . . . . . . . . . . . . I uXHXSXHXFXSXSXFXHXSXFXFXFXSXFXFXFXFXSXFXFXFXFXFXFXSXFXFXFXSXSXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXSXFXFXFXFXFXFXFXFXFXSX", -"SXSXFXFXFXSXFXSXFXSXFXSXSXSXFXFXFXSXSXSXSXFXSXSXFXFXSXFXSXFXSXFXFXFXSXFXSXSXFXFXFXSXFXSXSXFXSXFXSXFXSXHXSXSXFXSXSXFXSXFXSXFXSX,Xn . . . . . . . . . . . . n ,XFXSXHXSXSXSXHXSXSXSXSXSXSXFXFXSXSXFXSXFXSXSXFXSXFXFXFXFXSXFXSXFXFXSXFXFXSXSXSXFXSXSXSXSXSXSXFXFXSXFXSXFXFXSXFXSXFXSXSXSXFXSXFX", -"SXSXFXSXSXFXSXSXSXFXSXSXSXFXFXSXFXSXSXFXSXSXSXFXSXSXSXSXSXFXSXSXSXSXSXFXSXFXFXSXSXSXSXSXSXSXFXSXSXSXSXSXSXHXSXSXFXSXSXSXSXSXSXSXSX-Xr . . . . . . . . . . . . . . . . e -XFXSXFXSXSXSXSXFXSXSXSXSXSXSXSXFXSXSXSXFXFXSXSXSXSXSXSXFXSXSXFXSXFXSXSXSXSXSXSXSXSXSXFXSXSXFXSXFXSXFXSXSXSXSXSXSXSXSXSXSXFXFXSXSXFX", -"FXSXSXSXSXSXSXSXSXFXSXFXSXSXSXSXSXSXSXSXFXSXSXSXSXSXFXSXSXSXSXFXSXFXSXSXSXSXSXSXFXFXSXSXFXSXSXSXSXFXSXSXSXSXSXSXSXSXFXSXFXSXSXSXSXFXSX4Xw . . . . . . . . . . r 4XSXSXSXSXSXSXSXSXSXSXSXFXSXSXHXFXSXSXSXFXSXSXSXSXFXSXFXFXSXSXSXSXSXSXSXSXSXSXSXFXSXSXFXSXSXFXFXSXSXSXSXSXSXFXSXFXSXSXFXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX*X7 . . . . . . . . . . . . 9 *XAXFXZXZXFXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXZXSXSXSXZXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXZXSXSXZXSXSXSXSXSXSXZXSXSXSXSXSXSXSXSXSXSXSXSXSXZXSXSXSXSXSXSXSXSXSXSXSXSXSXZXZXSXSXSXSXSXSXSXSXSXZX*X7 . . . . . . . . . . . . . . . 7 *XZXSXSXZXFXSXFXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXZXSXSXSXSXZXSXSXSXSXSXZXSXSXSXSXZXSXSXSXSXSXSXSXSX", -"ZXSXZXSXZXSXSXSXZXSXZXSXZXSXZXSXZXSXZXSXSXSXSXSXSXSXSXZXZXSXSXZXSXZXZXSXZXSXSXSXZXSXSXSXZXSXSXZXSXZXZXSXZXSXSXSXSXZXSXSXSXSXSXSXSXZXSXSXSXZXSXSXVX].* . . . . . . . . . . . * ].ZXZXFXSXZXSXZXZXZXSXZXSXZXZXSXSXZXZXSXSXSXZXSXSXSXZXSXSXZXSXSXSXSXSXSXSXSXZXSXZXSXSXSXSXSXSXCXSXSXZXSXSXZXSXSXZXSXZXSXSXZXSXSXZXSXSXSXZXZXSXSXZXSX", -"SXSXZXSXSXZXSXSXSXZXSXZXSXZXSXZXSXSXSXSXSXZXZXSXZXZXSXSXSXSXZXSXZXSXSXZXSXSXZXSXSXZXZXSXSXSXZXSXZXSXSXSXSXZXSXZXSXSXSXZXZXSXZXZXSXSXSXZXSXSXZXZXSXSXVX].= . . . . . . . . . . . . . = ].CXSXSXZXFXZXSXZXFXSXSXZXSXZXSXSXZXSXZXSXZXZXSXSXZXZXSXSXZXSXZXSXZXZXSXSXZXZXSXSXZXSXSXSXZXSXZXSXSXSXZXSXZXSXSXZXSXSXZXSXZXSXSXZXSXSXSXZXSXSXSXZXZXSXZX", -"ZXSXSXSXCXSXSXCXSXZXSXZXZXSXZXSXZXZXSXZXZXSXZXZXZXSXZXZXSXZXZXSXSXZXZXSXZXSXZXZXZXZXZXZXZXSXZXZXZXZXSXZXZXSXZXZXZXZXSXZXZXSXZXSXZXZXSXZXZXSXZXSXZXSXZXZXVXA.& . . . . . . . . . . . . # A.VXZXSXZXSXZXZXZXSXSXZXZXZXSXZXSXZXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXSXZXZXSXZXSXZXSXSXSXCXSXSXSXZXZXSXZXSXZXSXZXSXZXZXSXZXSXZXZXSXSXZXZXZXZXSX", -"SXCXCXSXSXCXSXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXmXA.o . . . . . . . . . o S.mXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXSXCXCXCXSXSXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZX", -"CXCXSXZXCXZXCXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXhX! + . . . . . . . . . . # ! hXZXZXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXZXZXZXZXZXZXZXZXZXCXSXZXCXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXZXZX", -"CXSXCXZXSXCXSXCXZXZXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXhX! + . . . . . . . . . . . . . . . . . O R hXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXSXCXZXSXCXSXZXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZX", -"CXZXCXZXCXZXZXZXCXZXZXCXZXZXZXCXZXZXCXZXCXZXZXZXCXZXCXZXCXZXCXZXZXCXZXZXZXZXZXCXZXZXZXCXZXCXZXZXCXZXZXZXCXZXZXZXZXZXCXZXZXZXZXZXZXZXZXCXCXZXCXZXZXZXCXZXZXZXCXZXZXCXZXZXhXI . . . . . . . . . . . . . o o U gXZXZXZXZXZXZXZXCXZXCXZXZXZXZXZXCXZXCXZXZXCXZXZXZXCXZXCXZXZXCXZXZXZXCXZXZXZXCXZXCXZXZXZXCXZXZXZXZXCXZXZXCXZXSXCXCXZXCXZXZXZXZXZXCXZXCXZXZXCXZXCXZXCXZXCXCXCXZXZXZXCXZXCXZX", -"ZXCXZXZXZXCXCXCXCXCXCXZXCXCXZXCXCXCXCXZXCXCXCXZXZXZXCXZXZXCXZXZXCXZXCXCXCXCXCXCXCXCXCXZXCXZXCXCXCXCXCXCXZXCXCXZXCXCXCXZXCXCXCXCXCXCXCXZXCXZXCXZXCXCXZXCXCXCXCXCXZXCXCXCXZXZXgXI . . . . . . . . . . . . . . . L gXCXZXCXCXCXCXCXCXZXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXZXCXZXCXCXCXZXCXCXZXCXCXCXCXZXZXCXCXCXZXCXCXCXCXCXCXCXZXCXCXCXCXCXCXZXCXCXCXCXCXCXCXZXCXCXZXZXCXZXZXZXCXCXZXCXCXZXZXCXCXCX", -"CXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXCXCXCXuXH . . . . . . . . . H uXBXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCX", -"CXCXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXuXH . . . . . . . H uXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXCXZXCXCXZXCXCXCXCXCXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCX", -"CXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCX4Xy . . . . . . . . . . . . . . n 4XCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXCX", -"CXBXBXCXCXCXCXBXCXBXCXCXCXCXBXCXCXCXBXCXBXCXCXCXCXBXBXCXBXCXCXBXCXCXCXBXCXCXCXCXCXBXCXCXCXCXBXCXCXCXCXCXCXBXCXCXCXCXBXCXCXCXCXCXCXCXCXBXBXCXCXBXCXCXBXCXCXCXCXCXBXCXCXBXCXBXCXCXCXCXBXCXBXCX-Xw . . . . . . . . . . . r 4XCXCXBXCXBXCXCXBXCXCXCXCXCXCXCXCXCXCXCXBXCXCXCXCXBXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXBXCXCXCXCXCXCXCXBXCXCXCXCXBXCXCXCXBXBXCXCXCXCXCXBXCXCXCXBXCXCXCXBXCXCXCXCXCXCXBXBXCXBXCXCXCXBXCXCXCXCXCXCXCX", -"CXBXCXBXCXBXBXCXBXCXCXBXCXBXCXBXBXCXBXCXCXBXCXBXCXBXCXBXBXCXBXCXCXCXBXCXCXBXBXCXBXCXCXBXCXBXCXBXCXBXBXCXBXBXCXBXCXBXCXBXCXBXBXCXBXCXBXCXBXCXBXCXBXBXCXCXCXCXBXCXBXCXBXCXBXCXBXCXBXCXCXBXBXCXBXCX2Xq . . . . . . . . . . . . . . w 2XCXCXCXBXCXBXCXCXCXCXBXCXCXBXBXCXBXCXCXCXBXCXBXCXBXCXCXCXBXBXCXCXBXCXBXCXBXCXBXBXCXBXBXCXBXCXCXBXBXBXCXBXBXCXBXCXCXBXBXCXCXBXBXCXBXCXBXCXBXBXCXCXBXCXCXCXBXCXBXBXBXCXCXBXCXCXCXBXBXCXBXCXBXCXBXBX", -"BXCXBXBXBXCXBXBXBXBXBXBXBXCXBXBXCXBXBXBXCXBXBXBXBXCXBXBXCXBXBXBXBXBXBXBXBXBXCXBXBXBXBXBXBXCXBXBXBXCXBXBXBXCXBXBXBXCXBXBXBXCXBXBXCXBXBXBXCXBXBXBXCXBXBXBXBXBXBXBXCXBXBXBXBXBXCXBXBXCXBXBXCXBXBXBXCXMX*X8 . . . . . . . . . . . 7 *XBXCXBXBXBXBXCXBXBXBXBXBXBXBXBXCXBXBXBXBXBXBXCXBXBXBXBXBXBXBXBXCXBXBXBXBXCXBXBXBXCXBXBXBXCXBXBXBXBXBXCXBXBXBXCXBXBXBXBXCXBXBXCXBXCXBXBXBXCXBXBXCXBXBXBXBXBXBXBXBXCXBXBXBXCXBXBXBXBXCXBXBXCXBXBXBXCXBX", -"BXBXBXBXBXBXBXBXBXBXCXBXBXBXBXCXBXBXBXBXCXBXBXCXBXBXCXBXBXBXBXCXBXBXBXBXCXBXBXCXBXBXBXBXCXBXBXBXBXCXBXBXBXCXBXBXCXBXBXBXCXBXCXBXBXBXBXBXCXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXCXBXBXCXBXBXBXBXCXBXCXBXBX*X3 . . . . . . . . . . . . . . . 3 *XMXBXBXCXBXBXBXBXBXBXBXBXBXBXBXBXBXBXCXBXBXCXBXBXBXBXCXBXCXBXBXBXBXCXBXBXBXCXBXBXBXCXBXBXCXBXCXBXBXCXBXBXBXBXCXBXBXBXBXCXBXBXBXCXBXBXCXBXCXBXBXBXBXBXCXBXCXBXBXBXBXCXBXBXCXBXBXCXBXBXBXCXBXBXBXBXBXCXBXBX", -"BXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXkXF.= . . . . . . . . . * ].zXBXMXCXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBX", -"BXBXBXBXBXBXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXNXBXBXBXNXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXMXF.* . . . . . . . % F.zXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXNXBXNXBXBXBXBXBXBXNXBXBXBXBXNXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXNXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBXBX", -"BXBXBXBXNXBXBXBXNXBXNXBXBXBXBXNXBXNXBXNXNXBXNXBXNXBXNXBXBXBXBXNXBXBXBXNXNXNXBXNXBXNXBXNXBXNXNXBXNXBXNXBXBXBXBXNXBXzXBXNXNXBXzXBXBXNXNXBXNXBXNXBXBXNXNXBXBXBXBXNXBXBXNXBXNXBXNXBXNXBXNXBXBXBXBXNXMXBXMXNXNXMXBXBXBXMXA.# . . . . . . . . . . . & A.kXBXBXzXBXBXNXNXBXNXBXzXBXBXBXBXBXBXzXBXBXBXNXBXNXBXBXNXNXBXNXBXBXBXNXBXBXNXBXNXNXBXBXBXNXBXBXBXBXzXNXBXzXBXBXBXBXNXBXBXzXBXBXBXBXNXNXBXBXzXNXBXNXBXBXNXNXBXNXBXBXNXNXNXBXNXBXNXNXBXNXBXNXNXBXNXNXBXBXNXNXBXNXBXNXBX", -"NXBXNXBXBXBXBXNXBXNXBXBXBXBXBXBXBXNXBXNXBXBXBXNXBXNXBXNXBXBXBXBXBXBXNXBXBXBXNXBXBXBXNXBXBXNXNXBXNXBXBXBXNXBXNXBXNXBXBXBXBXzXzXBXBXNXBXNXBXBXBXNXNXBXNXBXNXBXBXBXNXBXBXNXNXBXBXNXBXNXBXBXBXBXBXBXBXBXzXBXBXBXNXBXNXBXBXhXA.# . . . . . . . . . . . . + A.kXBXBXBXNXBXNXBXBXBXBXzXzXBXBXBXBXBXBXBXBXBXzXBXBXBXBXNXNXBXNXBXNXBXNXNXBXBXBXNXBXBXNXBXNXBXBXBXNXBXBXBXNXBXBXBXzXBXzXBXBXNXBXBXzXBXBXBXBXBXNXBXBXNXBXNXNXBXBXNXBXNXBXBXBXBXNXBXNXBXNXNXBXNXBXBXNXBXBXNXBXBXNXBXNXBXNXBX", -"NXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXBXNXNXNXNXBXNXNXBXNXzXBXBXBXBXBXNXBXNXBXzXBXBXNXBXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXzXNXBXBXNXNXNXNXNXBXNXNXBXhXR o . . . . # n.hXNXNXMXzXBXNXBXNXNXzXBXBXBXBXBXBXzXzXBXzXBXzXBXBXBXBXzXNXBXBXNXNXNXBXNXNXBXNXNXNXBXNXNXNXNXNXNXBXzXBXzXNXBXBXNXNXNXBXBXzXBXNXBXzXBXBXBXzXBXBXzXBXNXBXNXNXBXNXNXBXNXNXBXNXNXNXNXNXNXBXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNX", -"NXNXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXzXBXzXBXzXBXNXNXNXNXNXNXzXBXNXNXNXBXNXNXNXNXBXNXNXNXNXNXBXNXNXNXNXNXNXNXNXNXBXzXBXNXBXNXNXNXNXNXNXNXNXNXNXiXR . . . . . . . . . R iXMXBXNXBXBXzXBXNXNXNXNXNXBXzXBXBXzXzXBXBXzXBXzXBXBXBXBXzXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXBXNXNXBXNXNXNXNXNXNXNXBXNXNXNXzXBXzXBXBXzXzXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXNXNXNXBXNXNXNXNXNXBXNXNXNXBXNXNXNXNX", -"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXzXBXzXBXzXBXzXNXNXNXNXNXNXNXzXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXzXBXzXBXzXNXNXNXNXNXNXNXNXNXNXNXzXiXU . . . . . . . . . . . . . . . . . I iXNXBXMXzXBXzXNXBXzXNXNXNXNXNXNXNXzXBXzXBXBXzXBXBXzXzXzXzXzXBXzXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXzXNXNXNXNXNXNXzXBXzXNXNXNXNXNXNXBXzXNXBXzXBXzXBXzXBXzXBXzXNXNXzXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNX", -"NXNXNXNXNXNXNXNXNXNXNXNXNXNXNXzXNXNXNXzXBXNXNXNXNXBXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXzXNXNXNXNXNXBXzXBXzXzXBXzXBXzXBXzXBXNXNXNXNXzXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXNXNXNXNXBXNXNXNXNXNXzXBXNXNXNXNXNXNXNXNXNXzXNXNXNXNXNXMXNXNXuXU . . . . . . . . . . I uXNXNXNXzXNXNXNXzXNXNXNXNXNXBXNXNXNXNXNXBXzXBXzXBXzXzXBXzXBXzXBXBXBXBXBXNXNXBXNXNXNXNXNXNXNXNXNXzXBXNXNXNXNXNXNXNXzXNXNXNXNXNXNXNXBXNXNXBXzXBXzXBXzXzXBXNXzXNXBXzXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXBXzXNXNXNXNXNXNXNXNXNXNXNXNX", -"NXNXNXNXNXNXNXzXNXNXNXzXNXNXNXNXNXNXNXNXzXNXzXNXNXzXNXzXNXNXzXNXNXzXNXNXNXzXNXNXzXNXzXNXNXNXNXNXzXNXNXNXzXBXzXBXBXzXBXzXBXzXBXzXNXzXNXNXNXNXNXNXzXNXNXNXNXNXzXNXNXNXNXzXzXNXzXNXNXzXNXzXNXNXNXNXzXNXBXzXNXNXzXNXNXNXNXNXNXNXNXzXMXMXNXzXNX4XH . . . . . . . . . H uXNXNXNXNXNXNXNXNXNXNXNXNXNXzXNXzXNXzXNXBXzXzXBXzXBXzXBXBXzXBXzXBXzXzXzXzXzXNXNXzXNXzXNXzXNXzXNXNXNXNXzXNXNXzXNXNXNXNXNXNXNXNXzXzXBXNXzXNXzXzXBXzXBXzXBXBXzXNXBXzXzXNXBXzXNXNXNXNXNXzXNXzXNXzXNXNXNXNXzXNXNXNXNXzXBXNXzXNXNXNXNXNXNXNXNXNXlX", -"NXNXlXNXNXzXzXNXNXzXzXNXNXzXNXNXNXNXNXzXNXNXNXzXBXzXzXNXzXNXNXNXzXNXzXNXNXNXNXNXzXNXNXzXNXNXzXNXzXNXzXzXzXzXzXBXzXzXzXzXzXBXBXzXNXNXzXNXNXNXzXNXzXNXzXNXNXzXNXlXNXzXzXNXNXNXNXzXzXBXzXNXNXzXNXNXzXBXzXzXzXNXNXNXNXNXzXNXNXzXzXNXNXzXzXNXzXNXNX5XA . . . . . . . I 4XNXzXNXNXNXNXNXNXzXNXzXNXzXNXzXNXNXzXNXzXBXzXzXzXzXzXzXzXBXzXBXzXzXzXBXzXzXBXzXzXNXNXNXzXNXNXzXNXNXzXzXNXNXNXNXNXzXNXzXNXzXNXNXzXzXNXNXzXBXzXNXBXzXzXBXzXBXzXBXzXNXBXzXzXNXBXzXzXzXNXNXzXNXNXzXNXNXzXNXNXNXzXzXzXzXNXzXzXNXzXNXNXNXNXNXlXNXNXNX", -"zXlXNXzXzXNXzXzXzXNXzXzXNXzXzXzXzXzXNXzXzXzXzXzXzXNXzXzXNXzXzXzXzXNXzXzXzXzXzXzXzXzXNXzXzXzXNXzXzXzXNXzXzXBXzXzXzXBXzXzXzXzXzXzXzXzXzXzXzXNXzXNXzXNXzXzXNXlXNXNXzXNXzXzXzXzXzXzXzXzXzXzXNXzXzXzXzXzXNXzXNXzXzXzXzXzXNXzXzXNXzXzXzXNXzXzXNXzXNXNXzX4Xn . . . . . . . . . . n 2XzXzXzXNXzXNXlXNXfXlXNXNXzXzXNXNXzXzXzXNXzXzXzXNXzXBXzXzXzXzXzXzXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXNXzXzXNXzXzXzXzXzXzXNXzXzXzXNXzXzXzXzXNXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXNXzXzXzXzXzXNXzXzXzXzXNXzXzXzXNXzXzXzXzXNXzXNXzXNXzXzXNXzXNXlXNXlXNXNXNXlX", -"zXzXzXzXNXzXzXzXzXNXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXNXzXzXzXNXzXzXzXNXzXzXzXzXzXzXzXNXzXzXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXzXzXNXzXzXNXzXNXNXlXNXlXNXzXNXzXzXzXzXzXzXzXNXzXzXzXzXzXzXzXzXzXzXzXNXzXNXzXzXNXlXNXNXzXNXNXzXzXNXzXNXNXzXNXzXzX2Xn . . . . . . r 4XzXzXMXzXzXzXNXzXNXzXNXNXNXlXNXzXNXzXNXzXMXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXzXzXNXzXzXzXzXzXNXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXzXBXzXzXzXzXzXzXzXzXzXzXNXzXzXBXzXzXzXNXzXzXzXzXzXBXzXzXzXzXzXzXzXNXzXzXlXNXlXNX", -"zXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXNXNXlXNXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXNXzXNXlXNXfXNXlXzXzXzXzXzXzXzXzXzXzXzXzXNX*Xw . . . . . . . . 0 2XzXlXzXzXzXzXzXzXzXzXzXzXzXlXNXNXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXNXlXNXlX", -"zXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXlXNXNXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXzXNXNXNXfXNXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlX[.7 . . . . . . . . . 0 *XlXzXzXzXzXzXzXzXzXzXzXzXzXNXlXlXNXfXNXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzX", -"zXzXlXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXzXlXlXlXNXfXNXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXlXzXlXzXfXNXNXlXzXzXlXzXzXlXzXlXzXzXlXzXzXzXzXlXlX[.7 . . . . . . . . . . . . . . . 3 [.lXzXlXzXlXzXzXlXzXlXzXzXlXzXlXzXlXlXNXfXNXzXlXzXlXzXzXlXzXlXzXzXzXzXzXzXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXzXlXzXlXzXzXzXzXzXzXzXzXzXlXzXzXzXzXzXzXzXzXzXzXzXlXzXlXzXzXzXzXzXlXzXzXlX", -"lXlXlXlXlXNXlXlXNXlXlXNXlXlXlXNXlXlXlXlXlXlXlXNXlXlXNXlXlXNXlXlXlXlXNXlXlXNXlXlXlXNXlXlXlXlXlXlXNXlXlXlXlXlXlXlXlXlXlXlXNXlXlXlXlXlXNXlXlXzXzXlXNXlXlXlXlXlXlXlXlXlXlXlXlXNXlXlXNXlXlXNXlXlXlXlXzXlXzXlXzXlXzXlXlXzXlXzXlXzXlXzXlXlXzXlXzXlXzXlXlXzXlXzXlXzXlXlXzXlXjXF.= . . . . . . . : F.jXlXzXlXlXlXzXlXlXzXlXlXzXlXlXzXlXlXlXzXlXlXzXzXlXlXzXlXlXlXzXlXlXzXlXlXlXNXlXlXNXNXlXlXlXNXlXlXlXlXlXlXlXNXlXlXNXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXNXlXlXNXlXlXlXlXNXlXlXNXlXlXNXlXlXlXlXlXlXlXlXlXNXlXlXNXlXlXlXlXlXlXlXlXNXlXlXlXNXNXlXlXNXlXlXlXlXlXlXlXlXlXlXlXlXlXlX", -"lXlXNXlXlXlXlXNXlXlXlXlXNXlXlXlXlXNXlXlXNXlXlXlXNXlXlXlXlXlXlXlXNXlXlXlXlXlXlXlXlXlXlXNXlXlXNXlXlXlXlXNXlXlXNXlXlXlXNXlXlXlXlXlXNXlXlXlXzXlXlXlXlXlXlXNXlXlXNXlXlXlXNXlXlXlXlXlXlXlXlXlXlXNXlXlXlXzXlXzXlXzXlXlXlXlXzXlXzXlXzXlXzXzXlXzXlXzXlXlXlXlXzXlXzXlXzXlXlXzXlXlXjXF.% . . . . . . . . . . * F.kXlXlXzXlXlXzXlXzXzXlXlXzXlXzXzXlXzXlXzXlXlXzXzXlXlXzXzXlXlXzXzXlXlXzXzXlXlXlXlXlXlXlXlXlXlXlXlXlXNXlXlXNXNXlXlXlXlXlXlXlXlXlXlXNXNXlXlXlXNXlXlXNXlXlXlXlXlXlXNXlXlXlXlXlXlXlXlXlXlXlXlXNXlXNXNXlXlXlXlXlXlXlXNXlXlXNXNXlXlXlXlXlXlXlXlXlXlXlXlXlXlXNXNXlXNXlXNXlXlXNXlXlX", -"lXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXzXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXdXA.# . . . . . # A.dXlXlXlXlXlXlXlXlXlXlXlXlXlXlXzXlXzXzXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlX", -"lXlXlXlXlXlXlXlXjXlXlXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXdXA.# . . . . . . . . . # A.dXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXzXfXzXlXlXlXlXlXlXlXlXzXzXfXzXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXlXlXlXlXlXlXlX", -"lXlXlXjXlXlXjXjXlXlXlXjXlXjXlXlXlXjXlXlXjXlXlXjXlXlXlXjXlXlXjXjXjXjXlXlXjXlXlXlXlXlXjXlXjXlXlXlXlXlXlXjXlXlXjXlXlXlXlXlXlXlXjXjXlXlXjXlXjXlXlXlXlXlXlXjXlXlXjXlXlXlXlXlXlXjXlXlXlXlXjXlXlXjXlXlXlXlXlXjXlXjXlXlXjXjXlXlXlXlXjXjXlXlXlXjXjXlXlXlXlXjXlXlXjXlXlXlXlXlXlXjXlXlXjXjXjXlXiXT . . . . . . + T iXjXlXlXjXlXlXjXlXlXlXjXlXlXlXlXlXlXjXzXlXfXfXfXlXlXlXjXlXlXfXlXlXfXzXfXlXlXzXlXlXjXlXlXjXlXlXlXlXfXlXlXlXlXlXjXlXlXjXlXlXlXjXlXjXlXjXjXlXlXlXlXjXjXlXlXlXlXjXlXlXlXlXlXlXlXjXlXjXlXlXlXjXlXlXlXlXlXjXlXjXjXlXlXjXlXjXjXlXlXlXlXlXlXjXlXlXjXjXlXjXjXlXlXlXjXlXlXjXlXjXlXlXlXjXlXjXlXlX", -"lXjXlXlXjXlXlXlXlXjXlXlXlXjXlXjXlXlXlXjXlXlXjXlXlXjXlXlXjXlXlXlXlXlXlXjXlXlXjXlXjXlXlXjXlXlXjXlXlXjXjXlXjXlXlXjXlXlXjXlXlXjXlXlXjXlXjXlXlXlXjXlXlXjXlXlXjXlXlXjXlXlXlXjXlXjXlXjXjXlXjXlXlXjXlXjXlXjXlXlXlXjXlXjXlXlXlXjXjXlXlXlXlXjXjXlXlXlXjXlXlXlXlXjXlXlXjXlXlXjXjXlXjXlXlXlXlXjXjXlXiXT . . . . . . . . . . . + R iXjXlXlXlXjXlXjXlXjXlXjXlXlXlXjXlXlXjXlXlXfXzXzXlXzXzXfXlXjXlXlXlXlXlXlXlXzXzXfXfXjXlXjXlXjXlXlXjXjXlXlXlXlXlXjXlXjXlXlXlXjXjXlXlXlXlXlXlXlXlXjXlXlXlXlXlXjXlXlXlXlXjXjXlXjXjXlXlXlXlXlXjXlXlXlXjXjXjXlXlXlXlXlXlXlXlXlXlXlXlXjXjXlXjXlXlXjXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXjXjXlXlXlXlXlXjX", -"jXlXjXlXjXlXjXlXlXjXjXjXlXlXjXjXlXjXjXjXlXjXlXjXlXjXjXjXjXlXjXlXjXlXjXlXlXjXlXlXjXlXjXlXlXjXjXlXjXlXlXjXjXlXjXlXjXlXlXjXjXlXjXlXlXjXlXjXlXjXlXlXjXlXjXjXjXlXjXjXjXlXjXlXjXlXjXlXlXjXlXjXlXlXjXlXjXlXjXjXlXlXjXlXjXlXjXlXjXlXlXjXjXlXlXjXlXjXjXlXjXlXjXlXlXjXjXlXjXlXlXjXjXlXjXlXjXlXlXjXlXjXwXI . . . . . . O I uXjXlXlXjXjXjXlXjXlXlXlXjXlXlXjXlXlXjXlXjXjXjXzXfXlXlXfXlXfXlXlXlXfXlXfXlXlXzXfXlXlXlXlXlXlXjXjXlXjXlXlXjXlXlXjXlXjXlXjXjXlXjXjXlXjXlXjXlXjXjXlXjXjXlXjXjXlXjXlXjXlXjXjXlXjXlXjXlXjXlXjXlXjXlXlXjXlXjXlXjXjXlXjXlXjXjXjXlXjXjXjXlXlXlXlXjXjXjXlXjXlXjXjXjXlXjXjXjXlXjXjXjXlXlXlXjXjXlXjXlXjXlX", -"jXjXjXjXjXlXjXjXjXjXlXjXjXjXjXjXjXjXlXjXjXjXjXjXjXjXlXjXjXlXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXlXjXjXjXjXjXjXlXjXjXjXjXlXjXjXjXjXjXjXjXjXjXjXjXlXjXjXjXjXjXjXlXjXjXjXjXlXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXlXjXjXjXjXjXjXjXjXlXzXjXwXI . . . . . . . . . . . . I wXlXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXlXfXjXjXjXlXjXjXfXlXfXfXzXfXlXlXfXlXlXfXlXfXfXfXzXfXfXlXfXjXlXfXjXlXjXjXjXjXfXjXjXjXjXjXjXlXjXjXjXjXlXjXjXjXlXjXjXjXjXjXlXjXjXjXjXjXjXjXjXjXjXjXjXjXlXjXjXjXjXjXjXjXjXlXjXjXjXjXjXjXjXlXjXjXjXlXjXjXjXjXjXjXlXjXjXjXjXjXlXjXjXjXjXlXjXjXjXjXjXjXjXjXlXjXjXjXjXjX", -"jXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjX5XM . . . . . A 5XjXjXjXjXjXfXjXjXjXjXjXfXjXjXjXjXjXjXfXfXfXlXjXjXjXjXjXfXlXfXfXlXfXfXfXzXzXfXfXzXlXfXfXfXfXfXzXfXzXfXlXfXfXlXfXlXjXjXlXfXfXlXlXfXlXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", -"jXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX4XM . . . . . . . . . . . M 5XjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXlXlXfXjXjXjXjXfXlXlXfXjXjXlXfXfXfXfXfXfXfXfXlXfXlXlXfXfXfXzXfXfXlXlXfXlXfXjXjXfXlXfXlXfXlXfXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjX", -"jXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXfXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXfXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXfXjXjXjXjXjXjXjX2Xv . . . . . . n 2XjXjXjXjXfXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXfXlXfXfXjXjXjXjXfXlXfXlXjXjXjXfXfXzXfXlXzXfXfXfXfXfXlXlXfXfXfXfXlXfXlXfXjXjXjXjXlXjXfXfXfXlXfXlXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXjXfXjXfXjXjXjXjXjXjXfXjXjXjXjXjXjXjXjX", -"jXfXfXjXfXjXfXfXfXjXfXjXfXjXfXjXfXjXfXjXjXfXjXfXfXjXfXjXfXjXjXfXjXjXjXfXfXfXjXfXjXsXjXjXfXjXsXjXjXjXfXjXfXjXfXfXjXfXfXjXfXfXfXjXfXjXjXfXfXfXjXfXjXfXjXjXjXfXfXjXjXfXjXfXfXjXjXfXfXjXfXjXfXfXjXfXjXjXfXjXjXfXjXfXjXfXjXjXjXfXfXjXjXjXfXjXfXjXfXjXjXfXfXjXfXfXjXfXjXjXfXjXfXjXfXjXjXfXfXjXfXjXjXfXjXjXfXjXjXjXjXjX2Xv . . . . . v 2XjXjXjXjXfXjXfXjXjXfXjXjXfXjXfXjXjXfXjXfXjXfXjXjXfXfXfXlXfXjXfXjXfXfXfXfXjXjXfXlXfXfXlXfXfXfXlXfXlXfXfXfXfXzXfXfXfXfXfXfXjXfXfXjXfXjXlXfXfXfXlXfXjXjXfXjXfXjXfXjXfXfXjXfXjXfXfXjXjXfXfXjXfXjXfXjXjXfXfXjXfXjXfXfXfXjXfXjXjXfXjXfXfXfXfXjXfXjXjXfXjXjXjXsXfXjXfXfXfXfXjXfXjXfXjXjXfXjXjXfXjXfXjXjXjXfXfXjXfXfXjXfX", -"fXfXfXfXfXjXfXfXfXjXfXjXjXfXfXfXfXfXfXfXfXjXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXjXjXfXfXjXjXfXfXfXfXfXfXjXfXfXjXfXjXfXfXfXfXjXfXjXjXfXjXfXfXfXfXjXjXfXfXfXfXjXjXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXjXfXjXfXfXfXfXfXfXfXfXjXjXfXfXfXjXfXfXfXfXfXfXfXfXfXfXjXfXjXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXjXfX*Xw . . . . . . . 0 *XsXfXfXjXjXfXfXfXfXjXfXfXjXjXjXfXfXfXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXjXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXjXfXfXfXfXjXfXfXfXjXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXjXfXfXfXjXfXfXfXjXjXfXfXfXfXjXfXjXfXjXsXjXfXfXjXfXfXjXfXjXfXjXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfX", -"fXjXfXfXfXfXjXfXfXfXfXfXfXfXjXfXjXjXfXfXfXfXjXfXfXfXfXfXjXfXjXfXjXfXjXfXjXfXfXfXfXjXjXsXfXfXjXjXfXjXfXfXjXfXfXfXfXfXfXjXfXfXfXfXfXfXfXfXjXfXfXfXfXfXfXjXfXfXfXfXfXfXjXfXfXjXfXjXfXfXfXjXfXsXfXfXfXjXfXfXfXfXjXfXfXfXfXjXfXjXfXfXfXfXfXfXjXfXfXfXjXfXjXfXfXjXfXfXfXfXfXfXjXfXfXfXfXfXjXfXjXjXfXfXfXjXfXfXfXjXfXjXfXfXsXfX[.7 . . . . . . 8 [.fXfXfXfXfXfXfXfXjXfXfXfXfXfXfXfXfXfXjXfXfXjXfXjXfXfXjXfXjXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXlXfXfXfXfXlXfXfXfXlXfXfXfXfXfXjXfXjXfXjXfXfXjXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXjXfXfXfXfXfXfXfXjXfXfXfXjXfXfXfXfXjXfXfXfXfXfXfXfXjXfXjXjXfXfXfXjXfXfXfXjXjXfXfXfXfXjXfXjXfXfXjXfXjXfXjXfXfXjXfXjX", -"fXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXsXjXfXfXfXfXfXfXfXjXfXfXjXfXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXdX[.2 . . . . . . . . . . . 3 G.fXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXsXjXfXsXfXfXfXfXfXjXfXfXfXfXfXjXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfX", -"fXfXfXfXfXsXfXfXfXsXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXsXfXfXfXfXfXfXfXsXfXfXfXfXfXsXfXfXfXsXfXsXfXfXfXfXsXsXfXfXsXfXfXfXsXfXsXjXfXfXfXsXfXfXfXfXsXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXfXsXfXfXfXfXfXsXfXfXfXfXfXfXfXfXfXsXfXfXfXfXfXfXfXfXfXsXfXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfXsXfXsXS.: . . . . . : S.sXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfXfXfXfXfXsXfXfXsXsXjXsXjXsXfXsXfXsXfXsXfXfXsXsXfXfXfXfXfXfXsXfXfXfXfXsXfXfXfX", -"fXfXsXfXsXfXfXfXsXfXsXfXsXsXfXsXfXfXsXfXfXsXfXsXfXfXfXsXfXsXfXfXsXsXfXsXfXsXfXfXfXsXfXsXfXfXfXsXfXsXfXfXsXfXfXsXfXjXsXsXsXfXsXsXsXsXfXsXsXfXsXsXfXsXfXfXsXsXfXsXfXsXfXfXfXsXfXsXfXfXsXfXfXsXfXfXfXfXsXfXfXsXfXfXfXsXfXsXfXfXsXfXsXfXfXfXsXfXfXsXfXfXsXfXfXsXfXfXfXfXsXfXfXsXfXfXsXfXfXsXfXsXfXsXfXfXsXsXfXfXsXfXsXfXsXfXsXfXsXfXfXsXS.% . . . . . . . X % S.sXsXfXfXfXsXfXfXfXsXfXsXfXfXsXfXsXfXfXsXfXsXfXsXfXsXfXfXsXsXfXsXfXsXfXsXsXfXsXfXfXfXsXfXfXfXfXsXsXfXfXfXsXfXfXsXfXfXsXfXfXsXfXfXfXsXfXfXsXsXfXfXsXfXsXfXsXfXfXfXsXsXsXfXfXfXsXfXfXfXfXfXfXfXsXfXsXfXfXfXfXfXsXfXfXsXfXsXfXjXsXsXfXsXfXfXsXfXsXfXsXfXsXfXsXsXfXsXfXfXsXfXsXfXfXsXfXsXfXsXsXfXfXsXsXsXfXfXfXsXfXfXsXfXsXfXfXsXfXfXsXfX", -"sXsXsXsXsXsXsXsXsXsXfXsXsXfXfXsXsXsXsXsXfXsXsXfXsXsXsXfXsXsXsXsXsXfXsXfXfXsXsXsXfXsXsXfXsXsXsXfXfXsXsXsXsXsXsXfXsXsXsXsXfXsXsXfXsXfXsXfXfXsXsXfXfXsXsXfXsXfXsXfXsXsXsXsXfXsXsXfXsXsXsXsXfXsXsXsXsXsXsXsXfXsXsXsXfXsXsXsXsXsXsXsXfXsXsXsXsXsXsXfXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXfXsXfXsXsXsXfXsXsXfXsXfXsXsXsXfXsXfXsXfXsXsXpXm.+ . . . . . # n.pXfXsXsXsXsXsXfXsXsXfXsXsXfXsXsXsXsXfXsXfXsXsXfXsXfXsXfXsXsXsXfXsXfXsXfXsXfXsXfXfXsXsXsXfXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXfXsXsXsXsXfXsXsXfXsXfXsXsXsXsXsXsXfXfXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXfXsXfXsXsXsXfXsXsXfXfXsXsXsXsXsXfXsXsXfXsXsXsXfXsXsXsXfXsXsXsXsXfXsXsXsXfXsXsXsXfXsXsXsXfXsX", -"fXsXfXsXsXsXsXsXfXsXfXsXsXfXsXsXsXsXsXsXsXsXfXsXsXsXsXfXsXsXsXsXfXsXsXfXsXsXsXsXsXsXfXsXfXsXsXfXsXsXsXsXfXsXsXsXsXfXfXsXsXsXsXsXfXsXsXfXsXsXfXsXsXfXsXsXsXsXsXfXsXsXsXsXsXsXfXsXsXsXsXfXfXsXsXfXsXsXsXfXsXsXsXsXsXsXsXfXsXfXfXsXsXsXsXsXfXsXfXsXsXsXsXfXsXsXsXsXfXsXsXfXsXfXfXsXsXfXsXsXfXsXsXfXsXsXsXsXsXfXsXfXsXfXsXsXsXsXsXsXsXsXfXsXsXiXm.& . . . . . & A.pXfXfXsXsXsXsXsXfXsXsXsXsXsXfXsXsXsXsXfXsXsXsXfXsXsXfXsXsXfXsXfXsXsXsXfXsXsXsXfXsXsXsXsXsXsXsXsXfXsXsXfXsXsXfXsXsXsXsXfXfXsXsXfXsXsXfXsXsXsXsXsXsXsXsXfXsXfXsXfXfXsXsXfXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXfXsXsXsXsXsXfXsXsXfXsXsXsXsXsXjXsXsXsXsXfXsXfXsXfXfXsXfXsXsXsXsXsXfXsXsXfXfXsXsXsXsXsXsXfXfXsXsXsXsXsXsXfXsXsXsXfXsXsXfXsXfXsXsXfXsXsX", -"sXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXwXT . . . . . . . X T wXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX", -"sXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXwXT + . . . . . . X T wXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXfXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX", -"sXsXsXaXsXsXsXsXsXsXaXsXsXsXsXsXsXsXaXsXsXaXsXsXsXsXaXsXsXsXsXsXaXsXsXsXsXaXsXsXsXsXsXsXaXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXaXsXaXsXsXsXsXsXaXsXsXaXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXaXsXsXsXsXaXsXsXsXsXsXsXaXsXsXsXsXsXaXsXsXsXsXaXsXsXsXsXsXsXsXsXaXsXsXsXsXaXsXsXsXaXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXaXsXsXaXsX5XI . . . . . X I 5XaXsXsXsXsXsXsXaXsXsXsXaXsXsXsXsXsXsXsXaXsXsXsXaXsXsXsXsXsXsXaXaXsXsXsXsXsXaXsXsXsXaXsXsXaXsXsXsXsXsXaXsXsXsXaXsXaXsXsXsXsXsXsXsXaXsXaXsXsXsXaXsXsXaXsXsXaXsXsXaXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXaXsXsXaXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXaXsXaXsXsXsXsXaXsX", -"sXsXaXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXaXsXsXaXsXsXsXsXsXaXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXaXsXaXsXsXaXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXaXsX5XI O . . . . . . . . . I 5XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXaXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXaXsXaXsXaXsXsXsXaXsXsXsXsXsXsXsXsXaXsXsXsXaXsXaXaXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXaXsXsXsXsXsXsXsXsXsXsXsXsXsXaXsXsXsXsXsXsXaXsXaXsXsXsXsXsXsXsXsXsX", -"sXsXsXsXsXsXaXsXsXaXsXaXsXaXsXsXsXaXsXsXaXsXaXsXsXsXaXsXaXsXaXsXsXsXaXsXsXaXsXaXsXsXaXsXsXsXsXsXsXaXsXaXsXsXaXsXsXsXaXsXsXsXsXsXaXsXsXaXsXaXsXaXaXsXsXsXsXsXsXsXsXsXaXsXaXsXaXsXaXsXsXaXsXaXsXaXsXsXsXaXsXaXsXaXsXaXsXaXsXsXaXsXsXaXsXaXsXsXsXsXsXsXsXaXsXaXsXaXsXaXsXaXsXaXsXaXsXsXsXaXsXaXsXsXsXsXaXsXsXaXsXsXaXsXaXsXaXsXaXsXsXsXsXsXaXsXaXsXsXaXsXsXaXsXsX3XA . . . . . M 3XsXaXsXsXaXsXaXsXsXaXsXsXaXsXsXsXaXaXsXaXsXsXaXsXsXaXsXaXsXsXsXsXsXsXsXaXsXsXaXaXsXsXsXsXaXsXsXsXaXsXsXsXaXsXsXaXsXaXsXsXsXaXsXsXaXsXaXsXaXsXsXsXsXsXaXsXaXsXsXsXsXaXsXaXsXsXsXsXaXsXaXsXsXsXsXsXsXsXaXsXsXaXsXaXsXsXaXsXsXaXsXsXsXsXsXsXsXsXaXsXsXaXsXsXaXsXaXsXaXaXsXsXaXsXsXaXsXaXsXsXaXsXsXsXsXaXsXsXaXsXaXsXsXaXsXsXsXaXsXsXaXsXsXsXsXsXsXsXaXsXaXsXaXsXsX", -"sXaXsXaXsXaXsXaXaXsXaXsXaXsXsXaXaXsXaXsXsXaXaXsXsXaXsXaXsXaXsXaXsXsXsXsXaXsXaXsXaXsXsXaXsXaXsXaXsXsXaXsXaXsXsXsXaXsXaXsXsXaXsXaXaXsXaXsXaXsXaXsXsXaXsXaXsXsXsXaXsXaXsXsXaXsXaXsXsXaXsXaXsXaXsXaXaXsXaXsXsXaXsXaXaXsXsXsXaXsXaXsXaXsXsXsXsXaXsXaXsXaXsXaXsXsXsXsXsXsXaXsXaXsXaXsXaXsXsXaXsXaXsXaXsXaXsXaXsXaXsXaXsXaXsXaXaXsXaXsXsXsXsXsXaXsXaXsXaXsXaXsXsXsXsXaXsX2XM . . . . . M 2XaXsXaXsXaXsXaXsXaXsXsXaXsXaXsXsXaXsXsXsXaXsXaXsXsXsXsXsXaXaXsXsXsXaXsXaXsXaXsXsXsXsXaXsXaXsXaXsXaXaXsXaXsXsXsXaXsXaXsXaXsXaXsXaXsXsXsXsXsXsXsXsXsXaXsXaXsXaXsXsXaXsXsXaXsXaXsXaXsXsXaXsXaXaXsXaXsXaXsXaXsXsXsXsXaXsXaXsXaXsXaXsXaXaXaXsXsXaXsXaXsXsXsXsXaXsXsXaXsXaXsXaXsXsXsXaXsXaXsXaXsXaXsXsXsXaXsXsXaXsXaXsXaXsXaXsXsXaXsXaXsXsXaXsXaXaXsXsXaXaXsXaXsXaXsXaXsX", -"aXsXaXsXaXsXaXsXsXaXsXaXsXaXsXaXsXaXsXaXsXaXsXaXaXsXaXsXaXsXaXsXaXaXaXaXsXaXsXaXaXaXaXsXaXsXaXsXaXaXsXaXaXaXaXaXsXaXsXsXaXsXaXsXsXaXsXaXsXaXsXaXaXsXsXaXaXaXaXsXaXsXaXsXaXaXsXaXaXsXaXsXaXsXaXsXsXaXsXsXaXsXaXsXsXaXaXsXaXsXaXaXsXaXaXaXaXsXaXsXaXsXaXsXaXaXaXaXaXaXsXaXsXsXaXsXaXaXaXsXaXsXaXsXaXsXaXsXaXsXsXaXaXsXaXsXaXsXaXsXaXaXaXaXsXaXsXsXsXaXsXaXaXaXaXsXaXsXsX{.v . . . . . . . . v {.sXsXsXaXsXaXsXaXsXaXsXaXaXsXaXsXaXsXaXaXaXsXaXsXaXaXaXaXaXaXsXsXaXaXaXaXsXaXaXsXaXaXaXaXsXaXsXsXaXaXsXsXaXsXaXaXaXsXaXsXaXsXaXsXaXsXaXaXaXaXaXaXaXaXaXaXaXsXaXsXaXsXaXaXsXsXaXsXaXsXaXaXsXaXsXaXsXaXsXsXaXsXaXaXaXaXsXsXaXaXsXaXsXaXsXaXsXaXaXsXaXsXaXaXaXaXsXaXaXsXaXsXaXsXaXaXaXsXaXsXaXsXaXsXaXaXaXaXaXaXsXaXsXaXsXaXsXaXsXsXaXsXaXaXsXaXsXaXsXaXsXsXaXsXaXsXaXsXaX", -"aXsXsXaXsXaXsXaXaXsXsXsXsXaXaXsXaXsXsXaXaXaXsXsXsXaXsXaXsXaXsXaXaXsXaXsXaXsXaXsXsXsXaXaXsXaXsXaXaXsXsXaXsXsXaXsXaXaXsXaXsXaXsXaXaXaXaXsXaXsXaXsXaXaXsXsXaXsXsXaXsXaXaXsXsXsXaXsXsXaXsXaXsXaXsXaXaXsXsXaXsXaXsXaXaXsXaXaXaXsXsXaXaXsXsXaXaXsXaXaXsXaXsXaXaXsXaXsXaXsXaXsXaXaXsXaXsXsXaXaXsXaXsXaXsXaXaXsXsXsXaXsXsXaXsXaXsXaXaXaXaXsXaXsXaXsXsXaXaXaXsXsXsXaXsXaXsXaXaXsXsX{.r . . . r {.sXsXsXsXaXsXsXaXaXsXaXsXaXaXsXsXaXaXaXsXsXaXsXaXsXsXaXaXsXsXaXsXaXaXsXaXsXaXsXsXaXaXsXsXaXaXsXsXaXsXaXaXsXaXaXsXsXaXsXaXsXaXsXaXsXaXaXsXsXaXsXaXsXaXsXsXaXsXsXsXsXsXaXaXsXsXaXsXaXaXaXsXsXsXaXsXaXsXaXsXaXaXaXsXsXsXaXaXsXaXsXaXsXsXsXaXaXaXsXsXaXaXsXsXaXsXaXsXaXaXsXsXaXsXaXaXsXsXsXsXaXaXsXaXsXaXsXaXsXsXsXaXaXsXaXsXaXsXaXaXaXaXaXsXsXsXaXsXaXsXaXsXaXaXaXsXsXsXaXaXsX", -"aXaXaXaXsXaXaXaXaXaXaXaXaXsXaXaXsXaXaXsXaXsXaXaXsXaXaXaXsXaXaXaXaXaXaXsXaXaXsXaXaXaXaXsXaXaXsXaXsXaXaXsXaXaXsXaXaXsXaXaXsXaXaXsXaXsXsXaXaXaXsXaXsXaXaXaXaXaXsXaXaXaXsXaXaXaXsXaXsXaXaXaXsXaXaXsXaXaXaXaXsXaXaXaXaXaXsXaXaXaXsXaXsXaXaXsXsXaXaXsXsXaXaXsXaXaXsXaXaXaXsXaXaXsXaXaXaXaXaXsXaXaXsXaXaXaXsXaXaXaXaXaXsXaXaXaXsXaXsXaXaXaXsXaXaXaXaXaXaXsXaXaXaXsXaXaXaXaXsXaXaXsXaX[.w . . . . w [.aXsXaXaXsXaXsXaXaXaXsXaXaXsXaXsXaXaXsXaXsXaXaXsXaXaXaXaXsXaXaXaXaXsXaXsXaXaXsXaXaXsXaXsXaXaXsXaXaXsXaXaXsXaXaXaXsXaXaXsXaXaXaXaXsXaXaXaXsXaXaXaXaXaXsXaXaXaXsXaXaXaXaXaXsXaXaXaXaXaXsXaXsXaXaXsXaXaXaXaXsXaXaXaXsXaXaXaXsXaXaXaXsXaXaXaXaXaXsXaXaXsXaXsXaXaXsXaXsXaXaXsXaXaXsXaXsXaXaXaXaXaXsXaXaXaXaXaXsXaXaXaXaXaXsXaXaXsXaXaXaXsXsXaXsXaXaXsXaXaXaXaXsXaXsXaXsXaXaXaXsXaXaX", -"aXsXaXaXaXaXaXsXaXaXsXaXaXaXaXsXsXaXaXaXaXsXaXaXaXaXaXaXaXaXaXsXaXsXaXaXaXaXsXaXaXaXaXsXaXaXsXaXaXaXaXaXaXaXsXaXaXaXaXsXaXaXaXaXaXaXaXsXaXaXsXaXaXaXaXsXaXaXsXaXaXsXaXaXsXaXaXaXaXaXaXaXsXaXaXaXaXaXsXaXaXaXaXsXaXaXaXsXaXsXaXaXsXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXsXaXaXsXaXaXaXsXaXaXsXaXaXaXsXaXaXaXaXaXaXaXaXsXaXsXaXaXaXaXaXaXsXaXaXaXsXaXaXsXaXaXaXsXaXaXaXaXaXpX[.8 . . . . 8 [.aXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXsXaXaXaXsXaXaXaXaXaXaXsXaXaXaXaXaXaXaXsXaXaXaXaXaXaXsXaXaXsXsXaXaXaXaXaXaXaXaXaXaXsXaXaXaXsXaXsXaXaXsXaXaXaXaXaXsXaXaXaXaXsXaXsXaXaXaXsXaXaXaXaXaXaXaXaXaXsXaXaXaXsXaXaXsXaXaXaXaXsXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXsXaXaXaXaXsXaXaXaXaXaXsXaXaXsXaXaXsXaXaXaXsXaXaXaXaXsXsXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXsX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXpXG.2 X . . 2 G.aXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXm.% X . . . . . . 2 S.pXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXS.: . . . . . . : S.yXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXsXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXyXaXaXaXeXn.# . . & n.wXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXyXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaX", -"aXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXyXaXaXaXaXyXaXaXaXyXaXaXaXyXaXyXaXaXaXyXaXaXaXaXaXyXaXaXaXyXaXaXaXyXaXaXaXaXaXaXaXyXaXaXaXaXaXaXyXaXaXaXaXyXaXaXaXaXaXyXaXaXyXaXyXaXaXyXaXaXaXaXyXaXaXaXaXyXaXaXyXaXyXaXaXaXyXaXyXaXaXyXaXyXaXaXaXyXaXaXaXyXaXaXyXaXaXyXaXaXaXaXaXaXyXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXyXaXaXyXaXyXaXaXaXyXaXaXyXaXaXaXyXaXaXaXyXaXaXaXaXaXyXaXaXaXaXyXaXaXaXeXn.+ . . . . . + n.eXaXaXaXaXyXaXyXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXaXyXaXaXyXaXyXaXaXaXaXaXyXaXaXaXyXaXaXaXyXaXaXyXaXaXaXyXaXaXyXaXaXaXyXaXaXaXyXaXaXyXaXaXaXyXaXaXaXyXaXaXaXyXaXaXaXaXaXaXyXaXaXaXaXyXaXaXaXaXaXaXaXaXaXyXaXaXyXaXaXaXaXyXaXaXaXaXaXyXyXaXaXaXaXyXaXaXyXaXyXaXaXaXaXaXaXaXyXaXaXyXaXaXaXaXyXaXaXyXaXaXyXaXaXyXaXaXyXaXaXaXyXaXyXaXaXaXaXaXaXaXyXaXyXaXaXaXyXaXyXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXaXyX", -"aXaXaXaXaXaXyXaXaXaXyXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXyXaXaXyXaXyXaXaXaXaXyXaXyXaXaXyXaXyXyXaXaXaXaXyXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXyXaXaXyXaXyXaXaXaXaXyXaXaXyXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXyXaXaXyXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXwXU # . . . + T wXaXaXaXaXaXaXyXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXyXaXaXyXaXyXaXaXaXaXaXaXyXaXaXyXaXyXaXaXaXaXyXaXaXyXaXaXaXaXyXaXaXaXyXaXaXaXaXyXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXyXaXaXyXaXaXaXaXyXaXaXyXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXyXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXyXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXyXaXyXyXaXyXaXyXaXaXaXyXaXyXaXyXaXyXaXaXaXyXaXyXaXyXaXaXaXaXyXaXyXaXyXyXaXyXaXaXaXaXyXaXaXyXaXaXaXaXaXyXyXaXaXaXyXaXyXaXaXaXaXyXaXyXaXaXaXaXyXyXaXaXaXaXyXaXyXyXaXyXaXaXyXaXaXyXaXyXaXaXaXaXyXaXaXyXaXaXyXaXyXyXaXyXaXaXyXaXyXyXaXyXaXaXaXaXyXyXaXyXaXaXyXyXaXaXyXaXyXaXaXaXyXaXaXyXaXaXaXaXaXaXyXaXaXyXaXaXaXaXyXyXaXaXaXaXyXyXaXyXaXaXyXaXyXaXaXaXyXaXaXyXaXaXaXaXaXaXyXaXyXaXaXyXaXyXaXyXaXaXaXaXaXaXyXwXU . . . . . X T 6XyXaXyXaXyXaXyXaXaXaXaXyXaXyXyXaXyXaXaXyXaXyXyXaXyXaXyXaXaXyXyXaXyXaXaXyXaXyXaXaXaXyXaXyXyXaXaXaXyXaXaXyXyXaXaXyXyXaXaXyXaXaXaXyXaXaXyXaXaXaXaXaXaXyXaXaXyXaXaXaXaXaXaXyXaXyXaXaXyXaXaXaXaXaXaXyXaXaXyXaXaXaXaXyXaXaXaXyXaXaXaXyXyXaXaXaXaXyXaXyXaXaXaXyXyXaXyXaXyXaXyXaXaXaXaXaXaXyXaXyXaXaXaXaXyXaXaXyXyXaXaXyXaXyXaXaXyXaXyXaXyXaXaXyXaXaXaXyXaXyXyXaXyXaXyXaXyXaXaXyXaXyXyXaXyXaXaXyXaXyXyXaXyXaXyXaXaXyX", -"aXyXyXaXaXyXaXyXaXyXaXaXyXaXyXaXaXyXaXyXaXyXaXyXyXaXyXaXyXyXaXaXaXaXyXaXyXaXyXaXaXyXyXaXyXaXaXyXyXaXyXaXaXyXaXyXaXaXyXaXyXaXyXaXyXaXyXaXyXaXyXaXaXyXaXaXyXaXyXaXaXyXaXyXaXyXaXyXyXaXyXaXyXaXyXaXaXyXaXyXyXaXyXaXaXyXaXaXyXaXaXaXyXaXyXaXyXaXyXaXaXyXaXaXyXaXyXaXaXyXaXyXyXaXyXaXaXyXaXyXaXaXaXyXyXaXaXyXaXyXyXaXaXyXaXyXyXyXaXaXaXyXaXyXyXaXyXaXaXyXaXaXyXaXaXyXyXaXyXaXyXaXyXaXaXaXyXyXaXyXaXyXyXaXyXaXyXyXaXyX5XS . . . I 3XaXyXaXyXaXaXyXaXyXaXyXaXyXaXyXaXaXyXyXaXyXaXaXaXaXaXaXaXaXaXaXyXaXyXaXaXyXaXyXaXyXyXaXaXyXaXyXaXyXaXyXaXaXyXaXaXyXaXyXaXaXyXaXyXyXaXaXyXaXaXyXyXaXyXaXyXaXyXaXyXyXaXyXaXyXyXaXaXaXyXaXyXaXyXaXyXyXaXaXaXyXaXyXaXyXaXaXyXaXyXyXaXaXaXaXaXyXaXyXaXyXaXaXaXaXaXaXyXaXyXaXaXyXaXyXaXyXyXaXaXaXyXaXaXyXaXyXaXyXaXaXaXaXaXyXaXaXyXaXaXaXyXaXyXaXyXaXyXaXyXaXyXaXaXaXyXaXyXaXyXaXaXaXaXaXyXaXaXyXaXaXaXaXaXaXaXyXaXyXaX", -"yXaXyXaXyXaXyXaXaXyXyXyXaXyXaXaXaXyXyXaXyXaXyXaXaXyXaXaXyXaXyXyXyXaXyXaXaXyXaXyXaXyXaXyXaXyXyXaXaXaXyXaXyXaXyXaXyXaXyXaXaXyXaXyXaXyXaXyXaXyXaXyXyXaXyXyXaXyXaXyXyXaXyXaXyXaXyXaXaXyXaXyXaXyXyXyXyXaXyXaXaXyXaXyXyXaXyXaXyXyXyXaXaXyXaXyXaXyXaXyXyXaXyXyXaXyXaXaXyXaXyXaXaXyXyXyXaXyXyXaXyXyXyXaXyXyXyXaXyXaXaXyXyXaXyXaXyXaXyXyXyXaXyXaXyXaXyXaXaXyXyXaXyXyXyXaXyXyXaXyXaXyXaXyXyXaXyXaXyXaXyXaXaXyXaXaXyXaXyXaXyXaX6XI . . . . I 6XaXyXyXaXyXaXyXyXaXyXaXyXaXyXyXyXaXyXyXaXaXyXaXyXyXyXyXyXyXyXyXyXaXyXyXaXyXyXaXyXaXyXyXaXyXyXaXyXaXyXyXaXyXyXyXaXyXyXaXyXaXyXyXaXyXaXaXyXaXyXyXaXyXaXaXyXyXaXyXaXyXaXyXaXyXaXyXaXyXyXyXaXyXaXyXaXyXaXyXyXyXyXyXyXaXyXyXyXyXaXyXaXaXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXaXyXaXyXaXaXyXaXyXyXaXyXyXyXaXyXyXyXaXaXyXaXyXyXyXyXyXaXyXyXaXyXyXyXaXyXaXyXaXyXaXyXaXyXaXyXyXyXaXyXaXyXaXyXyXyXyXyXaXyXyXyXyXyXaXyXyXyXyXaXyXaXyX", -"yXaXyXyXyXyXyXaXaXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXaXyXyXaXyXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXaXyXyXaXyXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXaXyXaXyXyXaXyXyXyXyXaXyXyXyXyXaXyXaXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXaXaXyXyXyXaXyXaXyXaXyXyXyXaXyXyXyXyXyXyXyXaXaXyXaXaXyXyXyXyXaXyXyXaXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyX3XM . M 3XyXaXyXaXaXyXyXyXaXyXyXyXyXaXyXyXaXyXyXaXyXyXaXaXyXyXaXaXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXaXyXaXyXaXyXaXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXaXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXaXyXaXyXyXyXyXyXaXaXyXaXaXyXaXaXyXaXaXyXyXyXyXyXyXaXaXyXaXaXyXyXyXyXaXaXyXaXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXyXaXaXyXyXyXyXaXyXyXyXaXyXyXaXyXyXyXyXaXyXyXaXyXyXyXyXaXyXyXyXaXyXaXyXyXyXaXyXyXyXaXyXyXaXaXyXyXaXyXyXyXyXaXyXyXyXyX", -"yXyXyXaXyXaXyXyXyXyXyXyXaXyXaXyXyXaXaXyXyXaXyXaXaXyXaXyXyXyXyXyXaXyXyXyXaXyXyXyXyXaXyXaXyXyXyXaXaXyXaXyXyXyXyXaXaXyXyXyXyXaXyXyXyXaXyXyXaXyXaXyXaXyXyXyXyXaXyXaXaXyXaXyXyXaXaXyXyXaXyXaXyXyXyXyXaXyXyXyXaXyXyXaXyXaXaXyXyXyXyXyXaXyXyXyXaXyXaXyXaXyXyXyXaXyXyXaXyXyXyXyXaXaXyXyXyXyXyXyXyXaXyXyXaXyXaXyXaXyXyXyXyXyXyXyXaXaXyXyXaXyXyXyXaXyXaXyXyXaXaXyXaXyXaXyXaXyXyXyXaXaXyXyXyXaXyXaXyXyXaXyXaXyXaXyXyXyXyXaXyXaXyXaXyXyX3XM . . . . M 3XyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXaXyXaXyXyXyXaXaXyXyXyXyXyXyXyXyXaXyXyXaXyXaXyXaXyXyXyXyXaXyXaXyXyXyXyXyXyXaXyXaXyXaXyXaXyXyXyXaXyXaXyXaXyXyXyXyXyXyXaXyXaXyXaXyXaXaXyXyXaXyXaXaXyXaXyXyXyXyXyXyXaXyXaXyXyXyXyXyXyXyXyXyXyXyXyXaXyXaXyXaXyXyXyXyXyXyXyXaXaXyXyXyXyXyXyXyXaXaXyXaXyXaXyXyXyXyXaXaXyXaXyXaXyXyXyXyXyXaXyXyXyXaXaXyXyXyXaXyXyXaXaXyXyXyXaXyXyXaXaXyXyXyXaXyXyXyXyXaXyXyXyXyXaXyXaXaXyXyXyXaXyXyXyXyXaXyXyXaXaXyXyX", -"yXyXyXyXyXyXaXyXyXyXaXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXaXyXyXaXyXaXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXaXyXyXyXaXaXyXyXyXyXaXyXyXyXaXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXyXaXyXyXyXyXyXaXyXyXyXyXyXaXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXaXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyX{.r . . . c {.yXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXaXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXaXyXaXyXaXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXaXyXyXyXaXyXyXyXaXyXyXyXyXyXaXyXyXyXyXyXaXyXyXyXaXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXaXyX", -"yXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXaXyXyXyXyXyXyX{.w . . . . w {.yXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXaXyXyXaXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXaXyXyXyXyXyXyXyXyXyXyXyXyXyXyX", -"yXyXyXyXyXyXyXyXyXyXyXyXyXrXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyX/.8 . 8 /.yXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyX", -"yXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXG.7 . . . 7 G.yXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyX", -"yXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXrXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXrXyXtXyXyXtXyXyXyXyXyXyXyXyXyXrXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXtXyXyXtXyXyXtXyXyXyXyXyXtXyXyXyXyXtXyXyXyXtXyXyXtXyXyXyXyXyXyXyXyXyXtXyXyXyXtXyXyXyXtXyXyXyXyXyXyXtXyXyXyXyXtXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXrXyXyXyXtXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXtXyXyXtXyXyXyXtXyXyXyXyXyXtXyXtXyXtXyXyXtXyXyXyXyXyXyXtXyXyXyXyXG.3 . . 2 G.tXyXyXyXtXyXyXyXyXyXtXyXyXyXyXyXtXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXtXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXtXyXyXyXtXyXyXyXtXyXyXyXyXyXtXyXyXyXyXyXyXyXyXtXyXtXyXyXyXyXtXyXyXyXyXyXyXyXyXyXtXyXyXyXyXyXyXyXyXyXtXyXyXyXyXtXyXtXyXyXyXyXtXyXyXyXyXyXyXyXyXyXyXyXrXyXyXyXrXyXyXyXrXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXyXrXyXyXyXyXyXyXrXyXyXrXyXyXyXyXyXyXyXyXtXyXtXyXyXyXyXtXyXyXyXyXyXtXyXyXyXtXyXtXyXyXyXyXyXyXyX", -"yXyXyXtXtXtXtXyXyXtXtXyXyXrXyXtXyXyXyXtXyXtXyXyXyXyXrXyXrXyXyXrXyXyXrXyXyXyXrXyXyXyXyXrXyXyXyXyXyXtXyXyXyXrXtXyXyXyXyXyXyXyXyXyXtXtXtXyXyXtXyXyXtXyXtXyXyXrXyXtXtXyXtXyXtXyXyXtXtXyXtXtXtXyXyXtXtXyXtXtXyXyXtXtXyXtXtXyXtXyXtXtXyXtXtXyXtXyXyXtXtXyXtXyXtXyXtXyXyXtXyXtXyXtXyXtXtXyXtXyXyXtXyXtXyXyXyXtXtXyXtXyXtXtXtXyXyXyXyXtXyXtXyXyXrXtXyXyXtXtXyXtXyXyXtXyXyXrXrXyXyXtXtXyXyXtXyXyXyXtXyXyXyXtXtXyXtXyXyXtXtXyXyXtXyXtXtXyXtXyXtXyXtXyXtXtXrXeXZ.3 . . 3 Z.tXyXyXtXyXtXyXtXtXyXtXyXyXtXtXyXtXtXyXyXtXtXyXyXtXyXtXyXrXyXrXyXtXyXyXyXtXyXyXyXtXyXtXyXtXyXyXtXtXyXtXyXtXyXtXtXtXyXtXtXtXyXyXyXyXtXtXyXtXtXtXyXtXyXyXyXtXyXyXtXtXtXyXtXtXyXtXtXtXyXtXyXtXyXyXyXtXyXtXtXyXyXyXyXtXtXtXyXtXtXyXyXtXtXyXtXtXtXyXtXyXrXtXyXtXyXyXtXtXyXtXtXyXyXyXtXtXtXyXyXrXyXrXyXyXyXyXyXyXyXyXtXyXyXrXyXrXyXrXyXyXrXyXyXrXyXrXyXrXyXrXyXyXyXyXyXyXrXyXyXyXyXyXyXyXrXtXyXtXyXtXyXyXtXtXyXyXyXyXtXtXyXtXyXyXtXtXyXyXtXyXyXtXtXyXtXyXrX", -"tXyXtXyXtXtXtXtXrXtXtXtXtXyXrXyXtXtXtXtXtXyXrXyXrXyXyXrXrXyXyXrXyXrXyXyXrXyXyXrXrXyXyXrXyXrXrXyXrXtXyXtXtXyXtXyXrXyXyXrXrXyXyXrXtXtXtXtXtXtXyXtXtXtXtXtXtXrXyXyXtXyXtXyXtXtXtXyXtXyXtXyXtXtXtXtXtXtXtXtXtXtXyXtXyXtXtXtXtXtXtXtXtXtXyXtXtXtXtXtXtXtXtXtXtXtXtXtXtXyXtXyXtXyXtXyXtXtXtXtXtXyXtXyXtXyXtXtXtXtXtXyXtXyXtXtXtXtXtXtXtXyXtXtXyXtXrXyXyXrXrXyXtXtXtXtXtXyXtXyXrXtXyXtXtXtXyXtXtXtXyXtXtXtXtXtXtXtXtXyXtXtXtXyXtXtXtXtXyXtXtXtXyXtXyXtXtXtXtXrXm.% . . . % m.eXtXtXtXtXyXtXyXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXyXyXtXtXtXrXyXyXrXyXrXyXrXyXtXtXyXtXtXtXtXtXtXtXtXtXtXyXtXtXtXtXtXtXyXtXtXtXtXtXtXtXtXtXtXtXtXtXyXyXtXtXtXtXtXtXtXtXyXtXyXyXtXyXtXtXtXtXtXyXtXtXtXtXtXtXtXtXtXtXtXtXyXtXyXtXtXtXtXtXtXyXtXyXtXtXtXtXyXtXtXtXyXtXyXtXyXtXtXtXtXtXtXtXyXtXyXyXrXrXyXyXrXrXyXyXrXrXyXtXyXyXtXyXrXrXyXyXrXrXyXyXrXrXyXyXrXrXyXyXrXrXyXyXrXrXyXrXyXyXrXyXrXyXyXtXtXtXtXtXyXtXyXtXyXtXrXrXyXrXyXtXtXtXtXtXtXtXyXrXyXtXyXyXtXtXtX", -"tXtXtXtXyXtXyXtXyXtXyXtXyXrXyXtXyXtXyXtXyXrXyXtXyXrXyXrXyXyXrXyXrXyXrXrXyXrXyXrXyXyXrXyXyXrXyXyXyXtXtXtXyXrXyXrXyXrXrXyXyXrXrXyXyXtXyXtXtXtXtXtXtXyXtXyXtXyXtXtXtXtXtXtXyXtXtXtXtXtXtXtXyXtXyXtXtXyXtXyXtXtXtXtXtXtXtXyXyXtXtXtXtXtXtXtXtXyXtXyXtXyXtXyXtXyXtXyXtXtXtXtXtXtXtXtXtXyXtXyXtXtXtXtXtXtXtXtXyXtXtXtXtXtXtXyXtXyXtXtXyXrXyXyXrXyXyXtXtXyXtXtXtXtXyXyXyXrXyXrXyXtXrXyXtXtXtXtXtXtXtXtXtXtXyXtXtXyXtXtXtXyXtXtXtXyXtXyXtXtXtXyXtXtXtXtXtXtXtXtXtXqXn.$ . . : m.qXtXtXtXtXtXtXtXtXtXtXyXtXyXyXtXyXtXyXtXtXyXtXtXtXtXtXtXtXyXyXtXtXyXtXyXtXtXtXtXyXrXtXyXtXtXtXyXtXyXtXtXtXtXyXtXyXtXyXrXtXyXtXyXtXyXtXtXyXtXyXtXtXtXtXtXtXyXtXtXyXtXtXtXtXtXtXtXtXtXtXyXtXtXtXtXtXyXtXtXyXtXyXtXyXtXtXtXtXtXtXyXtXyXtXtXtXtXtXtXtXyXtXtXyXyXtXtXtXtXtXtXyXtXyXtXyXtXtXtXtXtXrXyXyXrXyXyXyXyXrXyXyXrXtXyXrXyXyXyXyXyXrXyXrXyXrXyXyXrXyXyXyXyXrXyXyXyXrXyXyXrXyXrXyXyXrXyXrXyXyXtXyXtXtXtXtXtXyXrXtXyXyXtXyXrXyXtXyXtXyXtXtXtXtXtXtXyXrXyXrXyX", -"yXrXrXyXyXrXyXrXtXtXrXyXtXtXyXrXtXtXtXtXyXrXyXtXtXtXyXrXyXyXrXtXyXrXyXrXyXrXyXyXrXrXyXrXrXyXrXrXyXrXyXrXrXyXyXrXrXyXyXrXyXrXrXyXtXtXyXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXyXrXrXyXrXrXyXrXyXrXyXtXtXtXtXrXyXyXrXyXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXyXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXeXn.+ . . # n.eXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXyXrXtXtXtXtXtXtXtXtXyXrXtXyXtXtXtXtXtXtXyXrXtXrXyXrXyXtXtXtXtXtXyXrXrXyXrXyXtXtXtXtXtXtXtXtXtXtXtXtXrXyXrXrXyXrXrXyXrXrXyXrXrXyXrXrXyXrXrXyXrXyXyXrXrXyXyXrXtXyXyXrXrXtXtXtXyXrXyXrXyXrXyXyXrXrXyXrX", -"rXrXyXrXrXyXrXyXrXrXyXrXrXtXrXyXrXtXtXtXrXrXrXtXtXrXrXyXrXrXrXtXrXrXrXyXyXrXrXrXrXyXyXrXyXrXrXyXrXyXrXyXyXrXrXyXyXrXrXyXrXyXrXrXrXtXrXyXtXtXtXtXtXrXtXtXrXtXtXtXtXtXtXtXtXtXtXrXtXtXrXtXtXtXrXtXtXtXtXrXtXtXrXtXtXtXrXtXtXtXtXtXtXtXtXtXrXtXtXtXtXtXrXtXtXtXtXrXtXtXrXtXrXtXtXrXtXtXtXtXtXrXtXtXtXtXtXtXrXtXtXtXtXtXtXtXrXtXtXtXyXrXrXyXrXrXyXrXrXrXrXrXtXrXtXrXtXrXrXyXrXyXrXrXtXtXrXtXtXtXrXtXtXtXrXyXtXtXrXtXtXtXrXtXtXtXtXrXtXtXrXtXtXtXrXtXrXtXtXtXtXrXeXrXtX6XU + O U 6XtXrXtXrXyXtXtXtXtXtXrXtXtXtXtXtXtXtXtXtXtXrXtXtXtXtXtXtXrXtXrXtXtXtXrXtXrXtXtXtXtXtXrXtXtXtXtXrXtXtXrXtXtXtXtXrXtXtXtXrXtXtXtXrXtXtXtXrXtXtXrXtXrXtXtXtXtXrXtXrXtXrXtXtXtXrXtXtXtXtXrXtXtXtXrXtXtXtXtXrXtXtXtXrXtXtXtXtXrXtXtXrXtXtXtXtXtXrXtXrXtXtXtXrXtXtXtXtXrXtXtXtXtXrXtXtXtXrXyXtXrXtXrXrXyXtXrXtXrXrXyXyXrXrXrXrXtXrXtXrXyXrXrXrXrXtXtXrXtXrXtXtXtXtXrXtXtXyXrXrXyXyXrXyXrXrXyXyXrXyXrXrXyXrXyXrXrXyXrXrXyXyXrXrXyXrXrXrXyXtXtXtXrXrXrXrXyXyXrXrXrXrXyXyXrX", -"rXyXrXyXrXrXrXrXtXrXyXrXtXrXrXrXrXtXrXtXrXyXrXrXrXrXrXrXyXrXtXrXrXyXrXrXrXyXrXyXrXrXrXrXyXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXyXrXyXtXrXrXrXrXrXtXrXtXrXtXrXtXrXtXrXrXtXrXtXtXrXrXtXrXtXrXtXrXtXtXrXtXrXtXtXrXtXrXtXtXrXtXrXtXrXtXrXrXrXtXrXtXrXtXrXrXtXrXtXrXtXtXtXrXtXrXtXtXtXtXtXrXrXtXrXtXrXtXrXtXrXrXrXrXtXrXtXrXtXrXrXrXtXrXtXyXrXrXrXyXyXrXrXyXrXyXrXtXtXrXtXrXrXrXrXrXtXrXyXrXtXrXtXrXtXrXtXrXrXrXrXrXrXtXrXrXtXrXtXrXtXtXtXtXrXtXrXtXrXtXrXtXtXtXrXrXtXrXtXtXtXrX6XU . . . O U 6XtXtXrXrXrXtXrXrXrXtXrXtXrXtXrXrXrXtXrXrXtXrXtXrXtXrXrXrXtXrXtXrXtXrXtXtXtXrXtXrXrXtXrXrXtXrXtXrXtXtXrXtXrXrXtXrXtXrXtXrXtXrXtXrXtXrXtXtXrXtXrXtXtXrXtXrXtXrXtXrXtXtXrXrXtXtXrXtXrXtXrXrXtXrXtXtXtXrXtXrXtXrXtXtXrXtXrXtXrXtXrXrXtXrXtXtXtXrXrXtXrXtXtXrXtXrXtXrXrXtXrXtXtXrXtXtXrXrXrXrXrXtXrXrXtXrXrXrXrXtXtXrXtXrXrXrXyXrXtXtXrXyXrXrXrXyXrXtXrXtXrXtXtXtXrXrXtXrXtXyXrXyXrXrXyXrXrXyXrXrXrXyXrXrXrXrXrXrXyXrXrXrXrXrXrXrXrXrXyXrXrXrXyXrXtXrXyXrXrXrXyXrXyXrXrXrXrX", -"rXrXrXrXyXrXrXyXrXyXrXrXrXyXrXyXtXrXtXrXrXrXyXrXyXrXyXrXrXrXrXyXrXrXyXyXrXrXrXrXyXrXyXrXrXrXyXrXrXyXrXyXrXrXyXrXrXrXyXrXrXrXrXrXrXyXrXyXrXtXrXtXtXtXtXrXtXtXrXrXtXrXtXrXrXtXtXrXtXrXtXrXtXtXrXtXrXtXrXtXtXrXtXrXtXtXrXtXrXtXrXtXtXtXrXtXrXtXrXtXrXtXtXtXrXtXrXtXtXrXtXtXtXrXrXtXrXtXrXtXrXtXtXtXrXtXrXtXtXrXtXtXrXtXtXtXtXtXrXtXrXrXyXyXrXrXrXyXrXrXyXrXrXtXtXtXrXyXyXrXtXrXtXrXtXrXtXtXrXtXtXrXrXyXrXyXrXtXrXrXrXtXtXtXrXtXrXrXrXtXrXtXtXtXrXrXtXrXrXtXtXrXtXrXrXtXtXtXrX6XS . . S 6XrXrXtXrXtXtXrXrXtXrXtXrXrXtXtXtXrXtXtXrXrXtXrXtXrXtXrXtXrXrXtXtXtXtXtXrXtXrXtXtXtXtXtXrXtXtXrXtXrXtXtXrXrXrXtXtXrXtXrXtXtXtXrXtXrXtXrXtXtXrXtXrXtXrXtXtXtXtXtXtXrXtXrXtXtXtXrXtXtXrXtXrXtXtXrXtXrXrXtXtXrXtXrXtXrXrXtXrXtXrXtXrXtXtXrXtXrXrXtXtXtXrXtXtXrXtXrXtXrXrXtXrXyXrXtXtXrXrXtXrXtXrXyXrXtXtXrXyXrXyXrXrXtXtXtXrXtXtXrXtXrXrXtXrXrXyXyXrXrXtXtXrXrXtXrXrXtXtXrXtXrXrXrXrXrXrXrXrXyXrXrXyXrXrXrXyXrXrXyXrXrXyXrXyXrXyXrXyXrXrXrXrXyXrXrXtXrXrXrXyXrXrXrXrXrXyXrXyXrX", -"rXrXrXyXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXyXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXyXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXtXrXrXtXrXrXrXtXrXtXrXrXtXrXrXrXrXrXrXrXtXrXrXrXtXrXtXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXtX|.S . X o S 3XrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXtXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXtXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXtXrXrXtXrXrXtXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXyXrXrXrXtXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrX", -"rXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXeXrXtX{.M . M {.rXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrX", -"rXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrX{.M . M {.tXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXqXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrX", -"qXrXqXrXqXrXqXrXqXrXqXrXrXrXqXrXrXrXrXqXrXrXqXrXrXrXqXrXqXrXrXrXqXrXqXrXqXrXqXrXrXrXrXqXrXrXrXqXqXrXrXrXrXrXqXqXrXqXrXrXrXqXrXrXqXrXrXrXrXqXrXrXqXrXqXrXrXqXrXqXqXrXqXrXqXrXqXrXrXrXrXqXrXrXrXrXqXrXqXrXqXrXrXqXrXqXrXqXrXrXrXqXqXrXqXrX0XrXrX0XrXrXrX0XqXrXqXrXqXqXrXrXrXqXrXrXqXrXqXrXrXqXrXqXqXrXqXrXrXqXrXqXrXrXqXrXqXrXqXrXrXrXqXqXrXrXqXrXqXrXqXrXqXrXqXrXrXqXrXrXqXrXqXrXqXrXrXrXrXqXrXqXrXqXrXrXrXrXqXrXqXrXrXrXqXrXqXrXrXrXrXrXrXqXrXqXqXrXrXqXrXqXrXqXqXrXqXrXrXqXrXrXrXrXqXrXqX/.c . . w {.rXrXrXqXrXrXqXrXqXrXqXqXrXqXrXrXrXqXrXrX0XrXrXrXrXrXqXrXqXrXrXqXrXrXrXqXrXqXrXrXrXqXqXrXqXrXqXrXrXrXqXqXrXrXrXrXrXrXqXqXrXqXrXrXrXrXqXrXrXqXrXqXrXrXqXrXqXrXrXrXqXrXqXqXrXrXrXrXrXqXrXrXrXrXqXrXqXrXqXrXqXrXrXrXrXrXrXqXrXrXqXrXqXrXqXrXrXqXrXqXrXqXrXqXrXrXrXrXqXrXrXrXrXrXqXrXrXrXqXrXqXrXrXrXrXqXrXrXrXrXqXrXqXrXqXqXrXqXrXqXrXqXrXqXrXrXqXrXqXrXrXqXrXqXrXqXrXrXrXrXqXqXrXrXrXqXqXrXqXrXqXrXqXrXrXrXrXrXrXrXqXrXrXrXqXqXrXrXrXrXqXrXrXqXrXqXrXqXrXqXrXrXrXrXrXrXqXqXrXrXrXqXrXqXrXrXrX", -"rXqXrXqXrXqXrXrXrXrXqXrXqXrXrXqXqXrXqXrXrXrXrXrXqXrXrXrXqXrXqXrXrXrXqXrXqXrXrXqXqXrXqXrXrXqXqXrXrXqXqXrXrXrXrXqXqXrXrXrXrXqXqXrXrXqXrXqXrXrXrXqXrXqXrXrXrXqXrXrXqXrXqXrXqXrXqXrX0XrXqXrXrXrXqXrXrXrXqXrXqXrXrXrXrXrXrXrXrXqXrXqXrXqXrXqXrXrXrXqXrXrXqXrXqXrXrXqXrXrXrXrXqXrXqXrXrXqXrXqXrXrXrXrXqXrXqXrXqXrXqXrXrXqXrXqXrXrXrXqXrXqXrXrXrXqXqXrXqXrXqXrXrXqXrXqXqXrXrXqXrXqXrXrXqXrXrXrXrXqXrXrXqXrXrXqXrXqXrXrXqXrXrXrXrXqXrXqXqXrXqXrXqXrXqXrXrXqXqXrXrXrXrXqXrXrXqXrXqXrXrXqXrXrXrXrXrXqX9X{.c w /.rXqXrXqXrXqXrXqXrXqXrXrXqXrXqXrXqXqXrXrXrXrXqXrXrXqXqXrXrXrXrXqXrXqXrXqXrXqXrXrXqXqXrXrXrXrXqXrXrXqXrXqXrXrXqXrXrXrXrXrXqXrXqXrXqXrXrXqXrXqXrXqXrXrXrXrXqXrXrXrXrXrXrXrXqXrXqXrXqXrXrXqXrXqXrXrXqXrXqXrXrXrXrXrXqXrXqXrXrXrXrXrXrXrXqXrXqXrXqXrXqXrXrXrXqXrXrXqXqXrXrXqXrXrXrXrXrXrXqXrXrXqXrXrXrXrXqXrXrXqXrXqXrXqXrXqXrXrXrXrXrXrXqXqXrXrXrXrXrXrXqXqXrXrXrXqXrXqXrXrXqXrXqXrXrXqXrXrXrXrXqXrXrXqXrXqXrXrXqXrXrXrXrXrXrXrXrXrXrXrXrXqXrXqXrXrXrXqXrXqXrXrXqXqXrXqXrXrXqXrXqXqXrXrXqXrXqXrXrX", -"rXqXqXrXqXrXqXqXqXqXqXrXqXqXqXrXqXrXqXrXqXqXqXqXrXqXqXrXqXrXqXqXqXqXrXqXrXqXrXqXrXqXrXqXqXrXqXrXqXrXrXqXqXqXrXqXqXqXqXqXqXrXrXqXqXrXrXqXqXqXqXrXrXqXqXqXqXrXqXrXqXrXqXrXrXrXqXrX0XrXrXqX0XrXrXqXqXrXrXqXrXqXqXrXqXqXqXqXqXrXqXrXrXqXrXqXqXqXqXrXqXrXrXqXrXqXrXqXqXqXqXrXrXqXqXqXqXrXqXrXqXqXqXrXrXqXrXrXrXqXrXqXrXqXrXqXqXqXqXrXrXqXqXqXqXrXrXqXrXqXrXqXqXrXqXrXqXqXqXrXqXrXqXqXrXqXqXqXrXqXqXrXqXqXqXrXqXrXqXqXrXqXqXqXrXqXrXqXrXqXrXrXrXqXrXrXqXrXrXqXqXqXrXqXqXqXqXrXqXqXqXrXqXqXqXqXqXrXqXrX0X/.7 8 /.qXqXrXrXqXqXqXrXqXrXqXrXrXqXrXqXrXqXrXrXqXqXqXrXqXqXrXqXrXqXqXqXrXrXqXrXrXrXqXrXrXqXrXrXqXqXqXrXqXqXrXqXrXqXqXrXqXqXqXqXqXqXrXqXqXqXrXqXrXqXrXqXqXrXqXqXqXrXqXqXrXqXqXqXqXqXrXqXqXqXrXqXrXqXrXqXqXqXrXqXrXqXqXqXrXqXrXqXrXqXqXqXqXqXqXqXrXqXqXqXrXqXrXqXqXrXqXqXqXqXrXqXqXrXqXqXqXqXqXqXrXqXqXqXrXqXqXrXqXqXqXqXrXqXrXqXqXrXqXqXqXqXqXqXrXrXqXqXqXqXqXqXrXrXqXqXqXrXqXrXrXqXrXqXrXqXqXrXqXqXqXrXqXqXqXrXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXrXqXrXqXqXqXqXrXqXqXqXrXqXrXqXrXrXqXrXqXrXqXqXqXrXqXrXqXqX", -"qXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXrXqXqXrXqXqXqXqXqXrXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXrXrX0XrXrXqX0XrXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqX0XrXqXqXqXqXqXqXqXqXqXqXqXrXqXrXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXrXqXqXqXrXqXqXqXqXqXrXqXqXqXqXqXrXqXrXqXqXqXqXqXqXqXrXqXqXqXqXqXrXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXrXqXqXqXqXrXqXqXqXqXqX0XqXqXG.8 8 G.qX0XqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXrXqXqXqXrXqXqXqXqXqXqXqXqXqXrXqXqXqXqXrXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXrXqXqXqXrXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqX0XqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXrXrXqXqXqXqXqXqXqXqXrXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXqXqXrXqXqXqXqXqXqXrXqXqXqXqXqXqXqXqXqXqXrXqXqXqXrXqXqX", -"qXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXrX0X0XqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXZ.2 . > Z.rX0XqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX", -"qXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXrX0XqXqXqXqXqXqXqXqXqX0XrX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XZ.: : Z.9XqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqX0XqXqXqXqXqXqX", -"qXqXqXqXqXqXqXqXqXqX0XqX0XqXqXqXqXqXqX0XqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqX0X0XqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqX0XqXqXqXqXqX0XqXqXqXqX0XqXqXqXqXqXqXqXqX0XqXqX0XqXqX0XqXqXqXqXqXqXqXqXqXqXqXqX0XrXqXqXqXqXqXqXqXqX0XrX0XrXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqX0XqXqXqXqXqXqXqXqX0XqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqX0XqXqX0XqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqX0XqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqX0Xm.% % m.0XqXqXqXqXqXqXqXqXqXqXqX0XqX0XqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqX0XqXqXqX0XqXqXqXqXqXqXqXqXqXqXqX0X0XqXqXqXqXqXqXqXqXqX0XqXqXqX0XqXqXqXqXqXqXqX0XqX0XqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqX0XqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqXqX0XqXqXqXqX0XqXqXqXqXqXqXqXqXqXqXqX0X0XqXqXqXqXqX", -"0X0XqXqX0XqXqXqX0XqX0XqXqX0XqXqXqXqXqX0XqX0X0X0X0XqX0XqXqX0XqXqXqX0XqXqX0XqXqXqXqX0X0XqXqXqX0XqX0XqXqX0X0XqXqXqX0XqXqXqX0XqXqX0XqX0XqXqXqX0X0XqXqX0X0XqX0XqXqXqXqXqX0XqX0XqX0XqX0XqXqX0XrX0X0XrXqXqXqXqX0XqXqXqX0XqX0XqXqXqX0XqX0XqX0X0X0XqX0X0XqX0XqXqXqX0XqX0X0X0XqX0X0XqX0XqXqX0X0XqX0XqXqXqXqXqXqX0XqX0X0XqXqX0XqX0XqX0XqXqX0X0XqX0XqX0XqXqX0XqX0XqXqXqX0XqX0XqX0XqXqX0XqX0XqXqXqX0X0XqXqXqX0XqX0XqXqX0XqX0XqX0X0XqX0XqXqX0XqXqX0XqXqX0X0XqX0X0XqX0X0XqXqXqX0XqXqXqXqX0XqXqX0XqX0X0X0XqX0XqX0XqXqX0XqXqXqX9XqXqX9Xb.% : b.6XqXqXqX0XqXqX0XqX0XqXqXqXqX0X0XqX0XqXqX0X0XqXqXqX0XqX0XqXqX0XqXqX0XqXqX0XqX0XqXqXqXqXqX0X0XqXqX0X0XqX0X0XqX0X0XqXqXqXqXqX0X0XqX0XqX0X0XqXqXqXqXqXqXqX0XqXqXqXqXqX0XqX0XqXqX0XqX0X0XqX8XqXqXqXqXqXqXqX0XqXqX0XqXqX0XqXqX0XqXqXqX0XqX0X0XqXqX0XqX0XqX0XqXqX0XqXqXqXqXqXqXqXqXqX0XqXqXqX0XqX0XqXqXqX0XqXqXqX0XqXqXqXqX0XqXqX0X0X0X0XqXqXqXqXqXqX0X0XqXqXqXqX0XqXqXqX0X0XqXqX0X0X0XqX0XqXqXqX0XqXqXqX0XqX0XqXqX0X0XqXqX0XqXqXqX0X0XqXqXqX0XqX0X0XqX0XqXqX0XqXqXqX0XqXqX0XqXqXqX0X0XqX0XqX0XqX0XqXqXqX0XqX0XqXqXqXqXqXqXqX", -"0XqX0XqX0XqX0X0XqX0X0X0XqX0XqXqX0X0X0XqXqX0X0X0X0X0XqX0X0XqX0X0X0X0X0X0X0X0X0X0X0XqXqXqX0XqX0XqX0X0X0X0XqX0X0XqXqX0X0X0XqX0XqX0XqX0X0X0X0XqX0X0X0XqX0XqX0X0X0X0X0X0X0X0XqX0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX0XqX0X0X0XqX0XqX0X0X0XrX0X0X0XqXqX0X0X0XqX0X0X0X0XqX0X0XqXqX0X0X0XqX0X0X0X0X8XqX0X0X0XqX0XqX0X0XqX0X0XqX0XqX0X0XqX0X0XqX0X0X0X0XqXqX0X0X0XqX0XqX0X0XqX0X0XqX0X0X0X0X0XqX0X0X0XqX0X0XqX0X0XqX0X0X0XqX0X0XqX0XqX0X0X0X0X0X0XqX0X0XqX0X0XqX0X0X0XqXqXqX8XqX8XqX0XqX0X0X0XqXqX0X0X0XqX0XqX0X0X0XqX0X0X0X0X0X6Xb.# + b.9XqX0X0X0X0XqX0X0XqXqX0X0X0XqX0XqX0X0XqX0X0XqX0X0X0XqX0XqX0X0X0X0X0X0X0X0X0XqX0XqX0X0X0X0X0XqX0X0X0XqX0X0XqX0X0X0XqX0XqX0X0XqX0X0X0X0X0XqX0XqX0X0X0XqX0X0X0X0X0X0X0X0X0X0XqX0X0XqX0X0XqX0XqXqXqX8X0XqX0X0X0X0X0X0X0X0X0X0XqX0X0X0X0XqX0XqX0X0X0XqXqX0X0X0X0X0X0XqX0X0X8XqXqX8XqX8X0X0X0X0X0XqX0X0X0X0X0XqX0X0X0XqX0X0X0XqX0X0X0XqX0XqX0XqX0X0X0X0X0XqX0X0XqXqX0X0X0X0X0XqX0X0X0XqX0XqX0XqX0X0X0X0X0XqX0XqX0X0X0XqX0X0XqX0X0X0X0XqX0X0X0XqX0X0XqX0X0X0X0X0X0X0X0X0XqXqX0X0X0X0X0XqX0X0XqX0X0XqXqXqX0XqX0XqX0X0X0X0X0X0X0X0X", -"0X0XqX0X0X0X0XqX0X0X0X0XqXqX0X0X0XqX0XqX0X0X0X0XqX0X0X0X0X0XqX0XqX0X0X0XqX0XqX0XqX0XqX0XqX0X8XqXqX0X0XqX0X0X0X0X0X0X0X0XqX0XqX0X0X0X0XqX0XqX0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0XqX0X0XqX0XqX0XqXqX0X0X0X0XqX0X0X0X0XqX0X0X0X0XqX0X0X0X0X0XqX0X0X0X0X0X0XqX0X0X0X0XqX0X0XqX0X0X0XqXqX0X0X0XqX0XqX0X0XqX0X0XqX0X0X0X0XqX0X0X0XqX8XqXqX0XqX0XqX0X0X0XqX0X0X0X0X0X0X0X0X0XqX0X0X0XqX0X0X0XqX0X0X0X0XqX0X0XqX0XqX0XqX0XqX0X0X0XqX0X0X0X0X0XqX0X0XqX0XqX0X0X0X0X0X0XqX0X0X0XqX0XqX0X0X0X0XqX0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X6XS S |.0X0X0XqX0XqX0X0X0X0X0X0X0X0X0X0XqX0X0XqX0X0XqX0X0X0X0X0XqX0X0X0XqX0XqX0X0X0XqX0X0XqX0X0X0XqX0XqX0X0X0XqX0XqX0X0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0XqX0X0X0X0X0XqX0X0X0XqX0X0X0X0X0X0X0X0X0XqX0XqX0XqXqX0X0XqX0X0X0X0X0X0X0XqX0X0XqX0XqX0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0XqX0X0X0X0XqX0X0X0XqX0XqX0XqX0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0XqX0X0XqXqX0XqX0X0X0X0X0XqX0X0XqX", -"0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8XqXqX8XqXqX8XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XqX8XqX0X8X0XqX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X7X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8XqX0X0X0X0X0X0X0X0X0X0X", -"0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X8X0X8X0X0X0X0X0X0X0X0X0X0X8X8X0X8X8XqX8X0X0X0X8X0X0X0X0XqX0X8X0X8XqX8XqX0X8X8X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X8X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X8X0X0X8X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X8X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X", -"0X0X0X0X0X8X0X0X0X0X8X0X0X8X0X0X8X0X8X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X8X0X0X8X0X0X0X0X0X0X0X0X8X0X8X0X8X0X0X0X8X0X0X0X0X0X0X8X0X8X0X0X0X0X0X0X0X0X8X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X8X0X0X8X0X8X8X0X8X0X0X0X8X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X8X0X0X0X8X0X8X0X0X8X0X0X0X8X0X8X0X0X8X0X0X0X0X0X8X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X8XqX8XqX8X0X0X8X0X8X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X8X0X8X0X8X0X8X8X0X8X0X0X0X8X0X0X0X0X0X0X8X0X0X0X8X0X8X0X0X0X0X8X0X8X0X0X0X8X0X0X0X0X8X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X8X0X8X0X0X8X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X8X0X8X0X0X8X0X8X0X0X8X0X0X0X0X0X0X0X0X8X0X8X0X0X8X0X8X0X0X0X0X0X0X0X0X8X0X0X0X8X0X8X0X0X0X0X0X0X8X0X0X0X8X0X8X0X0X0X0X0X0X0X0X8X0X0X0X0X8X0X8X0X8X0X0X8X0X0X8X0X0X8X0X0X8X0X0X8X0X8X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X8X0X0X8X0X0X0X8X0X0X0X0X0X8X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X8X0X0X0X0X0X0X8X0X0X0X8X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X8X0X8X0X8X0X0X0X8X0X0X0X0X0X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X0X8X0X0X8X0X0X8X0X8X0X8X0X8XqX8XqX0X0X8X0X8X0X0X8X", -"8X0X0X0X8X0X0X8X8X0X0X0X8X0X0X8X0X0X0X0X0X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X8X0X8X0X0X8X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X8X0X0X0X8X0X0X8X0X0X8X0X0X0X0X0X0X0X8X0X0X8X8X0X0X0X0X8X0X0X8X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X8X0X0X8X0X0X0X0X0X0X0X8X0X0X8X0X0X0X0X8X0X0X8X0X0X0X8X0X0X0X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X8X0X0XqX8X0X0X8XqX0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X8X0X0X0X0X8X0X0X8X0X0X0X0X0X0X0X0X8X0X0X0X0X0X0X8X0X8X0X8X0X0X0X0X0X0X8X0X8X0X0X0X0X0X8X0X8X0X0X0X0X0X8X0X0X0X0X0X8X0X0X0X0X8X0X0X0X8X0X0X0X8X0X8X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X0X0X0X0X8X0X0X0X0X8X0X0X8X0X0X0X0X0X0X0X8X0X0X8X0X0X8X0X8X0X0X0X0X0X0X0X0X0X0X0X0X0X0X8X0X8X0X0X8X0X0X8X0X0X8X0X8X0X0X8X0X8X0X0X0X0X8X0X0X0X0X8X0X0X0X0X0X0X0X0X8X0X0X8X0X8X0X0X0X0X0X0X0X0X8X0X0X8X0X0X8X0X0X8X0X8X0X0X8X0X0X0X8X0X0X0X0X0X0X0X0X0X0X0X0X8X8X0X0X0X0X0X8X0X8X0X0X0X0X0X8X0X0X8X0X8X0X0X8X0X0X8X0X0X0X0X0X8X0X0X0X0X0X0X0X8X0X0X8X0X8X0X0X0X8X0X0X8X8X0X0X0X0X0X0X8X0X0X8X0X8X0X8X0X0X8X0X0X8X0X0X8X0X0X0X0X0X0X0X8X0X0X0X0X8X0X8X0X0X0X0X0X0X0X0X8X0X0X8XqX0X0X8X0X", -"8X8X8X0X8X8X0X0X0X0X8X0X0X8X8X0X8X0X8X8X8X0X8X0X0X8X0X8X8X8X8X0X8X8X0X8X8X0X0X8X8XqX8X0X8X8X8X8X8X8X8XqX0X8X8X0X8X8X0X0X8X0X0X8X0X8X0X8X8X0X8X8X8X8X0X0X0X8X0X8X0X0X8X8X8X0X8X8X0X8X8X8X8X0X8X8X8X8X8X0X0X8X8X0X8X8X8X8X8X0X0X8X0X0X0X8X8X8X8X8X8X0X0X0X0X8X8X0X8X0X0X0X8X8X8X0X0X0X8X0X8X8X0X8X8X0X8X8X8X0X7X0X8X8X0X8X8X8X8X0X8X8X0X8X8X8XqX8X8X0X8X0X8X8X8X8X0X8X8X0X0X8X8X0X8X8X0X0X8X8X8X0X8X0X0X8X8X0X8X8X0X8X0X8X8X8X8X0X8X8X0X0X8X0X0X8X8X0X8X0X8X0X8X0X0X8X8X0X8X0X0X8X8X8X8X0X8X0X8X8X8X0X8X0X8X8X8X8X0X8X8X0X8X8X8X0X0X8X0X0X8X0X0X8X8X0X8X0X8X8X8X8X0X8X8X0X8X8X8X0X8X8X0X0X8X8X0X8X8X0X8X0X8X0X8X8X0X8X0X8X0X8X8X0X0X8X0X0X8X8X0X8X8X0X8X0X8X8X8X8X8X0X8X0X8X0X0X8X0X0X0X8X8X0X8X0X8X0X0X0X8X8X0X8X0X0X8X0X8X0X8X8X8X0X8X8X8X8X0X0X8X0X0X8X8X8X0X0X8X8X8X0X8X0X8X0X0X0X0X8X8X0X8X0X0X8X0X8X8X0X8X0X8X8X0X8X8X0X8X0X0X8X8X0X0X8X8X8X8X0X8X0X0X8X8X0X8X0X8X8X0X8X8X0X8X0X0X8X8X0X8X0X0X8X0X8X8X0X8X8X0X8X8X0X8X0X0X8X0X8X8X0X0X8X0X0X0X0X8X0X8X8X8X0X0X0X0X8X0X8X0X0X8X0X0X8X8X0X0X0X8X8X8X0X8X0X8X0X8X0X8X0X8X0X8X0X0X8X8X0X8X8X0X8X8X8X0X8X0X8X0X8X", -"8X0X8X8X8X0X8X8X8X8X0X8X8X8X8X0X0X8X8X0X8X8X8X8X8X8X8X0X8X8X8X8X8X9X8X0X8X0X8X8X8X8X8X8X8X8X8X0X8X0X8X8X8X8X0X8X8X8X0X8X8X0X8X8X8X0X8X8X8X8X8X0X8X0X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X0X8X0X8X8X8X0X8X0X8X8X8X8X0X8X8X8X0X8X8X0X8X8X8X8X8X0X8X8X8X0X8X0X8X8X8X8X8X8X8X0X8X8X8X8X8X8X7X0X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X0X8X8X8X8X0X8X8X0X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X0X8X0X8X8X0X8X8X0X8X8X8X0X8X8X8X8X8X8X0X8X8X8X0X8X8X0X8X8X0X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X0X8X0X8X8X8X8X8X0X8X8X8X8X0X8X8X8X8X0X8X8X8X8X8X8X8X0X8X8X0X8X8X0X8X8X0X8X8X8X8X8X8X0X8X8X8X8X8X8X8X0X8X8X0X8X8X0X8X8X0X8X8X0X0X8X8X8X0X8X8X0X8X8X8X8X0X8X0X8X8X0X8X8X0X8X8X8X8X8X8X0X8X8X0X8X8X8X8X0X8X0X8X8X8X8X0X8X8X8X8X8X8X8X8X0X8X8X8X8X0X8X8X0X8X0X8X0X8X8X8X8X8X8X0X8X8X8X8X0X8X8X8X8X0X8X8X0X8X0X8X8X8X8X0X8X8X8X8X0X8X8X0X8X8X8X8X8X8X8X0X8X8X8X0X8X0X8X8X8X0X8X0X8X8X8X8X8X8X8X0X8X0X8X0X8X8X8X8X8X8X8X8X8X8X0X8X8X0X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X0X8X8X0X8X8X8X0X8X8X0X8X0X8X0X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X0X8X8X8X8X8X8X", -"8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X0X7X8X8X0X8X8X8X8X8X8X7X0X8X8X8X8X8X0X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8XoX0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X0X8X8X8X8X8X8X8X8X8X8X8X8X8X0X8X8X8X8X8X8X0X8X8X8X8X8X8X8X8X8X0X8X8X8X8X0X8X8X8X8X", -"8X8X8X8X8X8X7X8X8X8X8X7X8X8X7X8X8X8X7X8X8X8X8X7XoX8X8X8X8XoX8X8X8X8X8X8X8X7X8X8X7X8X8X7X7X8X8X7X8X8X8X8X8X8X7X8X8X8X8X8X7X8X8X7X8X8X7X8X8X7X8X7X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X7X8X8X8X8X8X8X8X7X8X8X8X7X8X8X8X8X8X7X8X8X8X7X8X7X8X8X7X8X8X8X8X8X8X7X8X8X7X0X7X0X7X8X8X8X8X8X8X8X0X7X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8XoX8X8X8X8X8X8XoX8X8X8X8X8X7X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X7X8X8X7X8X8X8X8X8X7X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8XoX8X8X8X0X8X8X8X8X8X8XoX8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X7X8X7X8X8X8X8X7X8X8X8X8X7X8X8X7X8XoX8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X7X8X8X8X8X7X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X7X8X8X8X7X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X7X8X8X8X8X8X8X7X8X8X7X8X8X8X8X8X8X7X8X8X7X8X8X8X7X0X7X0X7X0X7X7X0X0X7X7X0X7X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X7X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X", -"8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X7X8X8X7X7X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X7X8X8X7X8X8X8X8X8X7X8X7X0X7X7X0X8X7X8X8X7X0X8X7X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X7X8X7X8X8X7X8X8X7X7X8X8X8X8X8X8XoX8X8X8X8X8X8XoX8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X7X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X7X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X7X8X8X8X8X7X8X8X7X8X8X7X7X8X8X0X0X8X0XoXoX8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8X8XoX8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X7X0X0X7X7X0X7X7X0X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X8X8X8X8X8X8X7X8X8X8X8X8X8X8X7X8XoX8X", -"7X8X7X8X7X8X8X8X7X8X8X8X7X8X7X8X7X8X8X7X8X8X8X8X8X8X8X8X8X8X7X8X8X7X7X8X7X8X8X7X8X8X7X8X8X8X8X7X7X8X7X8X7X8X8X8X8X8X8X8X8X7X7X8X8X7X7X8X7X7X8X8X7X7X7X8X7X8X8X7X8X7X7X8X7X7X7X7X7X8X8X7X7X8X7X7X7X8X8X8X7X8X7X8X8X8X8X8X7X8X8X7X7X8X7X7X7X7X8X8X8X7X8X8X8X7X7X7X8X7X8X7X7X8X0X7X7X8X7X7X8X8X7X8X8X7X7X0X7X8X8X8X7X8X7X8X7X8X7X8X8X8X8X8X8X8X8X8X8X8XoX8X8X8X8X8X8X7X8X8X7X8X7X7X7X8X7X8X8X7X8X7X8XoX8X8X8X8X8X8XoX8X8X8X8X8X8X8X8X8X7X8X7X8X7X7X7X8X7X8X8X7X7X8X7X7X7X8X7X8X7X7X7X8X8X8X7X8X7X7X8X7X7X7X7X7X8X8X7X8X7X8X7X8X7X7X7X8X8X7X8X8X7X7X7X8X7X7X8X8X8X7X7X7X7X8X7X8X7X7X8X8X8X8X7X8X8X7X8XoX0XoXoX0XoX8XoX8X8X8X8X8X8X8X7X8X7X7X8X8X8X7X7X8X7X7X8X8X8X7X7X8X8X7X8X7X7X7X7X8X8X7X8X7X7X7X7X8X8X7X8X7X7X7X7X7X8X8X8X8X7X8X8X8X8X8XoX8X8X8XoX8X8X8X8X8X8X8X8X8X7X8X7X8X7X7X8X8X7X8X8X7X7X7X7X8X7X8X8X7X7X8X7X8X7X7X7X7X8X8X7X7X8X8X8X8X7X8X7X8X7X7X8X8X7X8X8X8X7X8X8X7X7X8X8X7X7X7X7X8X8X8X7X8X8X8X7X8X8X7X8X8X7X7X8X8X7X7X8X7X8X8X7X8X7X8X7X8X8X8X7X8X7X8X7X8X7X8X7X0X7X7X7X7X7X7X8X7X7X8X8X8X7X8X7X8X8X7X8X8X7X8X8X7X7X8X7X8X8X8X8X7X8X7X8X8X8X8X8X8X8X8X", -"7X7X8X7X7X7X7X7X7X7X7X7X8X7X7X7X8X7X7X7X7X7XoX8X8XoXoX8X8XoX8X8X7X8X7X7X8X7X7X7X7X7X7X7X7X7X7X7X8XoX8X7X8XoX7X7XoX8XoX8X7X8X8XoX8X7X7X7X7X8X7X7X8X7X8X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X7X8X7X7X7X7X7X8X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X9X7X8XoX8XoXoX8XoX8XoXoX8X8X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X8X7X8X7X7X8X8XoX8X8XoX8XoXoX8XoX8X8XoXoX8X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X8X7X8X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X8X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X8X7X8X7X7X7X7X7X7X7X7X7X7X7X8X7X8X8XoX8X0XoX8X8XoX8XoX8X8XoX8XoX7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X8X7X7X7X7X7X7X8XoX8XoX8XoX8XoXoX8XoX8X8XoXoX8X7X7X7X7X8X7X7X7X7X7X7X7X8X7X7X7X7X7X8X7X7X8X7X7X7X7X7X7X7X8X7X7X7X8X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X8X7X8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X0X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X8X7X7X8XoX7X7X8X7X7X7X7X7XoX8XoX8X8XoX", -"7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoXoX8XoX8XoX8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7X7XoX8XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoX8XoX8X8XoX8XoX8X8XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8XoX8XoXoX8X8XoX8XoX8XoXoX8XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoX8X8XoX8XoX8XoX8XoX8XoX8X8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8XoX8X8XoX8XoX8X8XoX8XoXoX8XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X", -"7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X8X8XoX8X8XoXoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8X7X7X7X7X7X7X7X7X7X7X8X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8XoX8XoX8XoX8XoXoX8XoX8X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoX8X8X8XoX8XoX8XoX8X8X8X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X0XoX8XoXoX8XoX8XoX8XoX8XoX8X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoX8X8XoX8X8XoX8XoX8X8X8X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X", -"7X7X7X7X7XoXoX7X7XoX7X7X7X7X7X7X7X7XoX7XoX7X8XoXoX8X8XoXoX8XoX8X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7X7XoX8XoX7X7X7XoX7XoX7X7XoXoX8XoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X.X7X7X7X7X7X7X7X7X7X7X7X7X7X7XXXXX7X7XXX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7XoX7X7X7XoXoX8X8XoXoX8X8X8X8XoXoXoX7XoX8XXX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoX8XoXoX8XoX8XoX8XoXoXoXoX8X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX8XoXoX8XoX8XoXoXoX8XoX8XoX8XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7X7X7X7X7X7X7X7X7X7XXX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X8XoXoX8XoX8X8XoX8XoX8XoXoXoXoX8X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7X7X7XXX7X7X7X7X7X7X7XXXXX7XXX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XXX7X7X7X7X7X7X7XXX7XXXXX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7X7XoX7X7X7X7X7XoX7XoX7X7X7XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XoX7XoX7X7X7X7X7XoX7XoX7X7X7X7X7XoX7X7X7XoX7X7X7XoX7XoX7X7X7XoX8XoX8X", -"oXoX7XoX7XoX7X7XoX7XoX7XoX7XoXoX7XoX7X7X7XoXoX7XoXoX7XoXoX8XoXoXoX7XoX7X7XoXoX7XoX7XoXoX7XoXoX7X7XoX7XoX7XoX7X7X7XoX7XoX7XoXoXoXoX7XoXoX7XoXoX7XoXoX7XoXoX7XoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X.X7XXX7X7X7X7X7X7X7X7X7X7X7XXX7X7X7X7X7XXX7X7XXX7XXX7X7X7X7X7XXX7X7X7X7XoX7XoX7XoXoX7XoX7XoXoX7XoXoX7XoXoX7XoXoXoX7XoXoXoX7X7X7XoXoXoX8XoXoX8XoXoXoXoXoXoX8XoX7X7XoX7X7X7X7X7X7XXX7X7XXX7X7XXX7X7X7XoX8XoXoXoX8XoXoXoX8XoXoX8XoXoXoXoX7XoXoX7XoXoX7X7XoX7XoXoX7XoXoX7X7X7X7X.X7X7X7X7X.X7X7X7X7X7X7XoX7XoX7XoXoXoX7XoX7XoX7XoX7XoX7X7X7X7XoXoX7XoX7X7XoXoX7XoX7X7XoX7X7X7X7X.X7X7X7X7X.X7X7X7X7X7X7XoX8XoX0XoXoXoXoX8X8XoXoXoXoXoX8X7XoX7XoXoX7XoXoX7XoXoX7XoX7X7XoX7X7X7X7XXX7X7XXX7X7X7X7X7X7XXX7X7X7X7X7X7X7XXX7X7XXX7XXX7X7X7X7XoXoX8XoXoXoXoXoXoX8XoXoX8XoXoXoX7XoXoX7XoXoX7XoXoX7XoX7X7XoXoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XXX7XXX7X7X7X7X7X7XXX7X7XXXoX7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7X7XXX7XXX7X7X7X7XoX7XoX7XoX7XoX7X7X7XoX7X7XoX7X7XoX7X7XoX7X7XoX7XoX7XoX7XoXoXoX7XoXoX7XoX7XoX7X7X7XoXoX7XoX7XoX7X7XoXoX7XoX7X7XoX7XoX7XoX7XoX7X7XoX7X7XoX7XoXoXoX", -"oX7XoX7XoXoX7XoXoXoX7X7XoXoXoXoX7XoX7XoXoXoXoX7XoX8XoXoXoX8X8XoX7XoXoX7XoXoXoXoXoXoX7XoXoXoXoXoXoXoXoX7XoXoXoXoX7XoX7XoXoXoX7XoXoXoX7X7XoXoXoXoX7X7XoXoX7XoXoXoXoXoXoX7XoX7X7XoXoXoXoX7X7XoXoXoX7XXX7XXX7X7XXX7X7X.X7X7XXX7XXX7X7X.X7X.X7X.X7X7X7X7XXXXX7X7X7XXXoXoX7XoXoX7XoXoXoXoXoXoX7XoX7XoXoX7XoX7XoXoXoX7XoX7XoXoXoX7XoX7XoXoXoX7X7XoXoXoX7XoXoXoXoX7X7XoX7X7XXX7XoXoX7X7XoXoX7XoXoXoX7XXXoXoX7XoXoX9XoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7X.X.X7X7X.X7X7XXX7X7XXX7X7X7X7XXX7X7X7XXX7X7XXXoXoX7X7XoXoXoXoX7XXXXX7XXX7X7X7XXX7X7X7XXX7X7X7X7X7X7X.X7X7X7X7X7X.X.X7X7X'.7X7X7XoXoX7XoXoXoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX8XoXoXoXoX7X7XoXoX7XXXXX7X7X7XXX7X7X7XXX7X7XXX7X7X7X7X7X7X7X'..X7X7X'.7X7XoXoXoXoXoXoXoXoX8XoXoXoXoXoXoXoXoXoX8XoXoXoXoXoXoXoXoX9XoXoXoXoXXXXX7XXX.X7X7X.X7X7X7X7X.X7X7X'.7XXX7X7XXX7X7X7XXXXX7X7XoX7XoXoX'.7X7X7X.X7X7X7X7X7X7X7X'.7X7X7XoXoX7X7XoXoXoXoX7X7XXX7XoXoX7X7XoXoXoXoX7X7XoXoX7XoXoXoXoX7XoX7XoXoXoXoX7X7XoXoXoXoX7XoXoX7XoX7XoXoXoXoX7XoX7XoXoXoXoX7X7XoXoXoXoX7XoXoXoXoX7X7XoXoXoXoX7XoXoX7X", -"oXoXoX7XoXoXoXoX7XoXoXoXoX7X7XoX7XoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7XoX7XoXoXoXoX7XoXoXoX7XoXoX7XoX7XoX7XoXoXoX7XoX7XoX7XoXoXoXoX7X7XoXoXoXoX7XoXoX7XoX7X7XoXoXoXoXoXoX7X7XoXoXoXoX7X7X7X7XXX7X7XXXXX7X7X7X7X7X.X7X7X7X7X7X7X7X7X7X.X7XXX7X7X7X7XXX7XXXoXoXoXoXoXoXoXoXoXoXoXoX7XoXoXoXoXoXoX7XoX7XoXoXoXoXoX7XoXoXoX7X7X7XoXoXoXoX7X7XoXoX7X7XoXoXoX7XXX7XXX7X7XoXoXoXXX7XoXoX7XoX7X7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX8XoXoXoX8XoXoXoXoXoXoX8XoXoXoXoXoX7X7X7X7X7X7X.X7X7X7XXX7X7XXXXX7X7XXXXX7X7XXX7X7X7XoXoXoXoX7X7XoXXX7X7X7X7X7XXXXX7X7XXXXX7X7XXXXX.X7X7X7X.X7X.X7X7X7X7X7X7X7X7X7XoXoXoXoX9XoXoXoXoXoXoXoXoXoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXXX7X7XoX7X7XoXXXXX7X7XXXXX7X7XXX7X7XXX.X7X.X7X7X7X7X7X7X7X7X7XoXoXoX8XoXoXoXoXoXoXoXoXoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7X7X7X7X7X7X7X7X.X7X7X.X7X7X7X7X7X7XXX7XXX7XXX7X7X7X7XXXoX7XoX7X7X7XXX7X7X7X7X.X7X.X7X7X7X7X7X7X7XoXoXoXoX7X7XoXoXoXXX7X7XoXoXoXoX7X7XoXoXoXoXoXoXoXoX7XoXoXoX7XoX7X7XoXoXoXoX7XoX7XoXoXoXoXoXoXoX7XoX7XoXoXoX7XoX7XoXoXoX9XoXoXoXoXoX7XoXoXoXoXoX7X7XoXoXoXoXoX", -"oXoXoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7XoXoXoXoXoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXX7XXX7XXX7X7XXX7X.X7X.X7X7X7XXX7X7X.X7X7X.X7X7XXX7X7X7XXX7XXX7XoX7XoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7X7X7XXXoXoXoXoX7X7XoXoXoXoXXX7XoXoXoXoXoXoXoXoXoXoXoX8XoXoXoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoX7X.X7X7X7X7X7X7X7XXX7XXX7X7XXX7X7X7XXX7X7XXXXX7XoXoXoXoXoX7XoXoX7XXX7XXXXX7X7X7XXX7XXX7XXX7XXX7X7X7X7X.X7X7X.X7X7X7X7X7X7X7X7X7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoX7XXXoXoXoXoX7XoX7XXX7XXX7XXX7XXX7X7XXX7X7X7X.X7X7X.X7X7X7X7X7X7XoXoXoXoXoXoXoX7XoXoXoX8XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXX7XXX7X.X7X7X7X7X7X7X7X7X7X7X7X7XXXXX7X7XXX7X7XXX7XXX7XoXoXoXoX7X7X7X7X7X7X7X7X7X7X.X.X7X.X'.7XoXoXoXoXoXoXoXoX7XoX7XXXoXoXoXoXoXoXoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7XoXoX7XoXoXoXoXoXoX7XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7X", -"oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7XXX7XXXXX7XXX7X7X.X7X7X.X7X.X7X.X7X7X.X7X7X7X.X7XXXXXXX7XXX7XXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXXXXX7XoXoXoXoXXXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX.X7X7X.X.X.X7X.XXX7XXX7XXXXX7XXXXXXX7XXXXX7XXXXXoXoXoXoXoXXXoXoXXX7XoXXX7XXXXXXX7XXX7XXX7XXX7XXX.X7X.X7X.X7X7X7X'.7X7X.X.X7X7X'.oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXX7XoXoXoXoXoXoXXX7XXX7XXX7XXX7XXXXX7XXX.X7X7X7X7X7X7X.X.X7X7X'.oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX7XXX7XXX7X7X.X.X7X.X.X7X7X7X'.7XXX7XXX7XXX7XXXXX7XXX7XXXoXoXoXoX.X7X7X'..X7X.X.X.X7X7X7X7X7X7X7XoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oXoXoXoXoX.XoXoXoXoXXXXXXXoXoXoXoXoXoXoXXXXXoXoXoXoXoXoXoXoX.XoXoXXXoXoXXXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXXXoXXXoXXXoXXXoXXXXXoXoXoXoXoXoXXX7XXX7XoXXXoXoXXXoXoXoXXXoXoXoXoXoXXXoX.XoXoXXXoXoXXXXXXXXXXX7X7X7XXXXX7XXX.X7X.X7X.X7X7X7X.X7X.X7X.X7X.X7X7XXX7X7X.X7XoXoXoXoXoXXXoXoXoXoXXXoXoXXXXXoXoXXXXXoXoXoXoXXXoXXXoXoXoXoXoXXXXXXXoXoXXXoXoXXXoXoXXXoXXXoXXXoXXXXXoXoXXXoXoXoXXXoXoXoXXXoXXXoXoXoXXXXXoXoXoXXXoXoXoXoXXXoXXXoXoXoXoXXXoXXXoXoXoXoXoXoXoXoXXXoX.X7X.X7X7X7X.X7X7X.X7XXX7X.X7X.XXX7X7XXX7XXX7XXXXXoXoXoXoXXXXXXXXXoXXXoXXXXX7X7XXXXXXXXXXXXX7X7X7X.X.X7X.X7X7X.X.X7X.X7X7X.X7X.XXXoXoXXXoXoXXXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXXXXXoXoXoXoXXXoXoXoXXXoXXXoXoXXX7XoXXXXX7XXXXX7XXXXXXX7XXX7X'.7X7X.X.X7X.X7X7X.X7X.XoXoXXXoXXXoXoXoXoXoXoXoXoXXXoXXXoXoXoXoXXXoXoXoXoXoXoXoXXXoXoXoX'.7X7X7X7X.X.X7X7X.X7X7X.X7X.X7XXXXX7XXXXXXX.X7XXXXXXXoXoXXXXXoX7X.X.X7X.X7X7X7X7X.X.X7X.X7X.X7XoX.XoXoXoXoXoXoXoXXXoXoXoXXXoXXXoXoXoXoXoXoXoXoXXXoXoXoXXXoXoXXXoXoX.XoXoXoXoXoXoXoXXXXXoXoXoXXXoXoXoXoXoXoXoX.XoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oX.XoXoXoXoXoXoXXXoXoXoXoXoXXXoXoX.XoXoXoXoXoXXX.XoXoX.XXXoXoXoXoXoXXXoXoXoXXXoXoXoXoXXXXXoXXXoXoXXXXXoXoXXXoXoXoXoXoXoXoXoXoXXXoXXXoXXXXXXXXXXXoXoXXXoXoXXXXXoXoXXXoXXXXXoXoXoXoXoXoXoXXXoXoXoX7X7XXXXXXXXXXX7X.X7X7X.X7X.X7X.X.X.X7X.X7X.X7X.X7X.X.X7X.X.X7X.XXXXXoXXXoXoXXXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX.XXXXXoXoXoXoXoXXXoXoXXXoXXXoXoXXXXX7X7XXXXX7XXXoXXXoXoXXXoXXXoXXXoXoXXXoXXXoXoXoXoXXXoXXXoXoXXXoXXXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXXXoXoXoX7X.X7X.X.X7X7X.X.X7X7XXX7X7X.X7XXXXXXXXXXXXX7XXXoXoXXXoXoXoXoX7X7XXXXXoX7XXXXXXXXX7XXX7X7X.XXXXX.X7X7X7X7X.X.X7X7X.X7X.X.X7X7X7XoXoXXXoXoXoXoXXXoXoXXXoXXXoXoXoXoXoXoXXXXXoXoXoXoXoXoXoXoXoXoXXXoXoXXXoXXX7XXXXX7XXXXXXXXX7XXX7XXXXXXX7X7X7X7X7X7X.X7X7X.X7X7X7XXXoXoXXXoXoXXXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXXXoX7X7X'.7X.X7X7X7X.X7X.X.X7X.X7X.X7XXXXXXXXX7X7X.X7XXXoXXXoXoXoXoX7X7X7X.X'.7X.X7X.X7X7X.X7X.X7X.XoXoXoXoXXXoXXXoXoXoXXXoXoXoXoXXXoXoX.XoX.XoX.XoXoXoXXXoXoXXXoXoX.XoXoXoXXX7XoX.XoXXXoXoXXXXXoXoX.XoXoXoX.XoXoXoXoX.XoXoXoXoXXXoXoXoX.XoX.XoXoXoXoX.XoXoXoX.XoXoX", -"oX.X.XoXoX.X.XoXXXoXoXXXXXXX.XoXoX.XoXXXoXoXoX.XoXoX.XoXoX.XoXoXoXoXXXoXoXXXoXXXoXoXXXoXoXoXXXXXXXoXXXoXXXoXXXoXXXoXoXXXoXXXXXXX7XXXXXXXXX7X7XXX.XoXoXoXXXoXXXoXoXXXXXoXoXoXoXXXoXoX.XoXXXoXXXXX'.7XXX7XXX7XXXXX.X7X7X.X.X7X.X7X.X7X.X7X7X.X.X7X.X7X7X.X.X7X.X7XXXoXoXoXXXoXXXoXoXoXoXXX.XoXoXXXXXXXoXXXoXXXXXXXoXXX.XoXoX.XXXoXoXXXXXXXoXXXXXoXoXXXXXoXXXXXXXXXXXoXXXoXoXXXoXoXXXoXoXoXXXoXXXoXXXoXoXoXoXXXXXXX.XoXoXoXXXXXoXXXoX.X.XoXoXXXXXoXoXXXXXoXXXoXXXXX.X7X.X7X7X.X.X7X7X.X.X7XXX.X7X.XXXXXXX7XXXXXXXXXoXXXoXXXXXXXoXXXXXoXXXoXXXXXXXXXXX7XXXXX.X7X.X7X7X7X.X.X.X.X7X.X.X7X.X7X.X7X.X.XoXXXXXoXXXoXXXXXoXoXXXoXXXoXXXoXoXoXXXoXXXoXoXoXXXoXoXXXoXXXoXXXXXoXXXoXXXXXXX7XXXXX7XXXXXXXXX7XXX7XXXXX'.7X'.'..X7X7X.X.X7X'.7XXXoXoXXXXXXXXXXXXXoXXX.X.XoXoXoXXXoXXXoXoXXXoXXXoXoXXXoXoXXXoXXX'.'.7X7X7X7X.X7X7X.X7X7X7X7X.X7X7XXXXXXX7XXX.X7XXXXXXX7XXXoXXXoX'.'.7X7X7X7X.X.X7X'..X7X7X.X.X7XoXXXoXoXXXoXXXXX.XoXXXoXXXXXoXoX.XoX.XoXoXoXoXoXoXXXoXXXXXoXXXoXoXoXoXoXoXoXoX.XoXoXXXoXXXoXoXXXoXoX.XoXoXoX.XoX.XoX.XoXXXoXoXXX.XoXoXoXoXoX.XoX.XoX.XoXoXoX.XoX", -".XoXoX.XoXoXoX.XXXXXXXXXoXXXoXXXXXoXXXXX.XXXoXXXoX.XoXoX.XoX.XoX.X.XoX.XXXoX.XoX.X.XoX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoXXXXXXXXXXXXXXXXXXXoX.X.XoXXXXXXXXX.XoXXX.X.XoX.XoX.XXXoX.XXXoXXXXX'.7XXXXXXXXXXXXX.X7X.X7X.X.X7X.X7X.X7X.X.X7X7X'.XXXXXXXX7X.X7X.XXXXXXXXXXXXXXXXX.XoX.XoXXXXXXXoXXXXXXXoX.XoXXXXXXXXXoXoX.XoXXXXXXXoXXXXXXXXXXXXXXXXXoX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoX.X.XoXXXoX.XoXXXoXXXXXXXXXXXXXXXXXoX.XXXoXXXXX.X.X7X7X'.7X7X'..X7X.X.X7X.X.X7XXXXX.X7XXXXXXXXXXXXXXXoXXXXXXXXXXXXXXXXX7XXXXXXXXXXXXXXX7XXXXXXX'.7X.X7X.X7X.X7X.X.X7X.X7X.X.X7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.X.XoX.XoXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7X7X7X7X7X'..X.X7X.X.X7XXXXXXXoXXXXXXXXXXXXXXXoXoX.X.XoXXXXXXXXXXXoX.XoX.X.XoX.XXXXXXXXX7X7X7X.X'.7X7X'.7X.X'.7X.X'.7X.XXXXXXXXXXXXX7X.XXXXXXXXXXXXXXXXX7X7X7X.X7X.X.X7X7X7X7X.X.X7X7X'.XXoX.X.XoX.XXXXXoXXXXXXXXXXXXXXX.XoXoXoX.X.XoX.XXXXXXXXXXXXXXXXXoX.XXXXX.XXXXXoXXXXXXXXXXXXXXXXX.X.XoX.XXXXXoXXXoXXXoX.XXXXXXXXXoX.X.XoX.XoXoX.X.XoXoXoX.X.XoX.X", -"oXoX.XoXXX.XXXXXXXXXXXXXXXXXXXoXXXXXXXXXXXXXXXXXXXXXXXXXoX.XoX.XXXXXXXXXXXXXXXXXXX.XoXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXX.XXXXX.XXXXXXXoX.XoXXXXXXXXXXX7X7XXXXXXXXX XXXXXXXXXXX.X.X7X7X'.7X.X.X.X7X.X.X.XXXXXXX.X7X.X.XXXXXXXXXXXXX.XXXXXXXXXXXXXXX.XXXXXXXXXXXXX.XoXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXoXXX.XoX.XXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXX.XXXXXXXXX.XXXXX.XXXXXXXXXXX.XXXXXXXXXXX7X7X'.7XXXXXXXXXXXXXXX.X7X X.X.XXXXXXXXXXX.XXXXXXXXX.XXXXX.XXXXXXXXXXXXXXXXXXXXX.X.X7X7X.X.XXXXX7X.X.X.X7X.X.X X7X'.7X.X7X7X'.7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XoXXXXXXXXX.XXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXX.XXX.X.X7X7X.XXX7X7X.X7X'.7X.X.X7X7X'..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XoX.XXXXXXXXXXXXXXXXXXX.XXX.X.X.X.X7X.X7X7X.X.X.X.X7X'.7X.X.X.XXXXXXXXXXX7X.XXXXXXXXXXXXX|..X7X.X7X.X7X.X.X.X'.7X.X.X7X7X'.7X.XXXXXXXXXXXXXXXXXXXXX.X.XXXXXXX.XoX.XoXXXXXXX.XXXXXXXXXXX.XXXXX.XXXXX.XXXXXXXXXXXXXXXXXXX.XXXXXoX.XXXXX.XXXXXXXXXXXXX.XXXXXXXXXXXXXXXXX.XXXXXXXXX.XXXXXXX.XXXXX", -".X.X.X.XXXXXXXXXXXXXXX.XXXXX.X.X.XXXXXXXXXXX.XXXXXXXXXXX.XoX.XoXXXXX.XoXXXXXXXXXXXXX.XXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXX.XXXXX.XXX.XXXXXXXXXXX.XXXXXXXXXXX.XoXXXXXoX.XXXXX.XoX.XXXoX.XXXXX7X'.XXXXXXXX7X XXXXXXXXX.X7X.X.X7X.X'.7XXXXX.X7X.X7X'.XX.X7X.X7XXXXXXXXXXXXXXXXXXXXX.XXXXXXXoX.XXXXXXXXXXXXX.XXXXXXX.XXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXX.X.XoX.XoXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXX.XoXXXXXoXXXXXXXXXXXXXXXXXXXXXXX.X.X7X.XXXXXXXXX.XXXXX7X.X.X7X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXX7X.X.X.X7X.X.X|..X.X7X7XXX.X7X7X7X7X'.7X.X.X7X.XXXXXXX.XXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXX.XXXXXXXXXXXXX.X.X.X.X X.X.X.X.X7X.X7X7X'..X7XXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXX7X7X.X.X.X.X X.X'.7X.X7X7X.X'.7XXXXXXXXXXXXX.X.XXXXXXXXXXXXX.X7X.X.X.X.X.X X7X7X7X.X7X.X.X.X7X.XXXoXXXXXXXXXXXXXXXXXXXoX.XXXXXXXoX.XoX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXX.XoXXXXX.XoXXXXX", -"XXXXoX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.X.XXX.XXXXX.XXXXX.XXXXXXX.XXXXX.XXXXXXX.XXXXXXX.XXX.XXXXXXX.XXXXX.XXXXX.X.XXXXX.XXXXXXX.X.XXXXXXX.XXXXXXX.XXXXXXXXX.XXX.XXXXX.XXXXX.X.XoX.X.XXXXX7X'.'.7X.X7X'.7X7X.XXX X.X.X.X.X7X'.7X.XXXXXXXXXXXXX7XXX X.X.X.XXXXX.XXXXXXXXXXXXXXX.X.XoX.X.XoX.XXXXX.XoX.XXX.X.XXXXXXXXXXXXXXX.XXX.XXXXXXX.XXXXXXXXXXX.XXX.XXX.XXX.XoXoX.XXX.X.XXXXXXX.XXXXX.XXXXXXXXX.XXX.XXX.XXXXXXXXX.XXXXXXX.XXXXXXX.X.XXXXXXXXXXXXXXXXX.X7X'.'.7XXX.X.XXX X7X XXX.X7X7X.X.XXXXX.X.XXXXX.XXXXX.XXXXXXXXXXXXXXX.XXXXX.X.XXX7X.X.X.X'..X7X.X.X.X.X.X X.X7X X'..X7X.XXXXX'.7XXXXXXX.X.XXXXXXXXX.XXXXX.XXXXX.X.XXX.XXX.XXXXX.XXXXX.XXXXX.XXXXXXXXX.XXXXX.X.XXX.X|..X.X.X.XXXXX.X7X.X7X.X7X.X7X7X.X.X'.XXXX7X'.XXXXXXXXXX.XXXXX.X.XXX.X.XXXXX.X.XXXXXoX.XXX.XXXXX.XXX.X.X.XXXXX.X.XXX X7X X.X7X7X7X'..X.X7X7X.XXXXXXXXX X7X X7X.XXXXX.X.XXX.X.X.X.X.X7X.X.X.X.X'..X7X.X'.7X'.7XXX.XXXXX.XXXXX.X.XXXXX.X.XXXXX.XXXXX.X.XXXXX.XXXXXXX.XXXXXXXXXXXXX.XXX.X.XXX.XXXXXXX.XXXXXXXXX.X.XXXXXXX.XXX.XXXXX.XXXXX.XXXXX.XXX.XXXXXXXXXXXXXXX.XoXXXXX.XXXXX", -".XoX.X.X.XXX.X.X.XXX.X.XXX.X.X.X.X.XXX.X.XXX.XXXXXXX.X.X.X.X.X.XXX.X.X.XXX.XXXXX.XXX.X.XXX.X.XXXXX.X.XXX.XXX.X.XXX.X.XXXXXXX.XXX.XXX.XXX.X.X.XXXXX.X.XXX.XXX.X.X.XXX.XoX.X.XXX.XXX.X.X.X.XXX.XoX.X7X'.7X XXX7X.X.X XXXXX7X.X.X7X.X7X.X.X.XXX.X.X XXX XXX7X.X.X7X.X.XXX.X.XXX.X.X.X.XXX.X.XXX.X.XoX.X.X.X.XXX.X.XXXXX.X.XXX.X.X.X.XXXXX.X.X.XXX.X.XXX.X.X.XXXXX.XXX.X.XoX.X.X.XXXXX.X.X.X.XXX.XXX.XXX.X.X.XXXXX.X.XXX.XXX.XXX.XXX.XXX.XXX.XXXXX.X.XXX.X.XXX.X.XXX.X7X.X.X.XXXXX.X.X.X XXXXX.X XXXXX.XXXXXXXXX.XXX.X.XXX.X.XXX.X.X.XXXXX.X.XXXXX.X.X.X.X7X7X.X'.7X7X.X.X.X7X.X.XXX7X X'.7XXXXX.X.X.XXX.XXXXX.X.X.X.XXX.X.XXX.XXX.X.XXXXX.XXXXX.XXX.X.XXX.XXXXX.XXXXX.XXX.X.XXXXX.X.X7X.X.XXXXX.XXX7X'..X.X.X.X.X X'.7X.X7XXXXX X7X.XXX.X.X.XXXXX.XXXXXXX.XXXXXXX.XXX.X.X.XXXXX.X.XXXXXXX.XXXXX.XXX.X.X7X.X.X.X X7X.X.X7X.X.X'.7X.XXX.X.X.X.X.X.X.XXX.X.XXXXX.X.X7X.X7X.X.X.X7X.X7X7X.X'.7X7X.X.X.XXX.X.X.X.XXXXXXXXX.XXX.XXX.XXXXX.X.XXX.X.XXX.XXX.X.XXX.X.XXX.X.X.XXX.XXXXX.XXX.X.X.XXX.X.XXX.XXX.XoX.XXXXX.XXX.X.X.X.X.XXX.X.XXX.XXX.XXX.X.X.XXX.XXX.X.XXXXX.XXX", -".X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.XXX.X.XXX.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.XXX.X.X.X7X.X.X.X.X.X.X.X.X.X7X.X.X.X.X.X.X.X.X.X.X.X.XXX X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.XXX.X.X.X.X.XXX.X.X.X.X.X.XXX.X.X.X.X.X.X.X.XXX.XXX.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.XXX.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X7X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X'.7X.X.X.X.X.X.X.X.X.X.X X7X X.X.X.XXX.X.X.X.X.X.XXX.X.X.X.X.XXX.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.XXX.X.X.X.XXX.X.X.X.X.X7X.X.X.X7X.X.X.X.X.X.X.X7X.X.X.X.X'.7X XXX.X.X.XXX.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X7X.X.X.X.X.X.X XXX.X.X.X.X.X.X.XXX.X.XXX.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X X7X.X.XXX7X XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.XXX.X.X.X.X.X.X.XXX.X.X.X.X.XXX.X.X.X.X.XXX", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X'..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X XXX.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX'. XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X'..X.X.X.X.X.X XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X'..XXX X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.XXX.X.X.X.X.X7X.X.X.X.X.X7X.X7X.X.X.X.X.X.X.X.X.X7X.X.X.X7XXX.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X7X.X.X.X.X.X7X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X XXX.X.X7X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X7X.X.X.X.X.X.X.X.X.X.X.X X X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X X.X.X X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X}..X.X}..X.X.X.X.X'.'.7X.X.X.X'..X'.'..X.X.X.X'..X.X.X'..X.X.X'. X XXX X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X X.X.X.X.X X.X.X.X.X.X.X.X X.X.X X.X.X.X.X.X.X}..X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X X.X.X X.X.X.X.X.X X.X.X.X.X.X.X.X.X'.'.7X.X.X.X'.XX XXX X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X'..X XXX.X.X.X.X.X.X X.X.X X X.X.X.X.X.X.X X.X.X.X.X.X X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X X.X}..X.X X.X.X.X.X.X.X.X'..X.X.X.X'..X.X.X.X X.X.X.X.X.X.X.X X.X.X.X X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.XXX.X X XXX.X'..X.X.X.X.X.X X.X.X.X.X.XXX'..X.X.X.X.X.X.X'.'..X.X.X X.X.X.X X X.X.X XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X X.X.X.X.X.X.X.X X.X.X.X.X.X X.X.X X.X.X.X X.X", -" X.X X.X X.X.X X X.X.X}.}..X.X.X.X X X.X.X.X X.X.X.X.X.X.X.X}..X.X X.X X.X.X X.X.X.X X.X X.X.X X.X X.X X X.X X.X.X X.X X.X.X X.X.X}..X}..X.X.X.X X.X}..X.X X.X.X X.X.X.X}.}..X.X.X.X.X}..X.X.X.X X.X.X X.X X X.X X.X.X X X.X.X.X.X.X X.X X.X X.X X.X.X X X.X.X X.X X X.X.X.X X.X X.X.X X.X X XXX.X.X X.X X.X X.X.X X X.X}..X.X.X X.X.X X.X.X X X X.X X.X.X X.X X.X.X X.X.X X.X X.X X.X.X X.X X.X X.X X.X.X X.X X.X.X X.X.X X.X.X X X X.X X.X.X X X.X X.X.X X.X X.X.X X.X X.X X.X X.X.X X X.X.X X X.X.X X.X X.X.X.X.X X.X X.X X X X.X X.X.X.X X.X X.X.X.X}.}..X.X.X X.X X.X X.X.X X.X X.X X.X X.X.X.X X X.X X.X.X X.X X.X X X.X X.X.X X.X X.X.X X.X X.X X.X X.X.X.X.X X}. X.X X.X.X X.X X.X.X X.X X.X X.X.X X.X X.X.X X.X.X X.X X.X.X X.X.X X.X.X X X X.X X.X.X X.X X.X.X X.X X.X X.X.X X.X X.X.X.X.X.X.X.X.X.X.X.X X X X.X X.X.X X.X X.X.X X.X X.X X.X.X X.X X.X.X.X}.}..X.X.X.X.X.X}..X.X X.X X.X X.X.X X.X X.X.X}..X.X.X.X}..X X.X.X X.X X.X.X X.X.X X.X X X.X X.X.X X.X X.X.X X.X.X.X.X X X.X X.X.X X X X.X X.X.X X.X X.X.X X X X.X X X.X X.X X.X.X X.X.X X.X", -" X X X X X X X X X X.X.X.X.X}..X X.X X X X X X X X.X}.}.}.}..X.X X X X X X X X X X X X X X X X X}..X X X.X X X X X X X X X X X X.X}..X X.X}..X}. X X X.X X X X X.X}.}..X.X.X.X}.}..X}..X.X}.}..X X X X.X X.X X X X X X.X X.X}.}. X X X X X X X X X X X X X X X X X.X X X X X X X X X X.X X X X X X X X X X X X X X.X X X.X.X}.}. X X X X X X.X X.X X X X X X X X X X X X X X X X.X X X X X X X X.X X X X X X X X X X X X X X X X.X X.X X X X X X.X X X X X X X X X X X X X X X X X X X X X X X X X X X.X X X X X X X X X X X X X X X X X X X X X.X}.}..X.X.X.X}. X.X X X X X X X X X X X.X X X X X X.X X X X X X X X X.X X.X X X X X X X X X X.X X X X X X X X X.X X.X.X.X X X X X X X X}..X.X}.}. X X X X X X X X X X X X X X X X X X X X X X X.X X.X X X X X X X X X X X X.X X X X X X X X X X.X'..X'.'..X.X'. X.X X.X X X X X X X X X X X X X.X X X X X X X X}..X.X.X.X}.}..X}..X X.X X X X X.X X X X X X X X.X}..X}. X X.X.X X X X.X X X X X X X X.X X.X X X X X X.X X X X X X X X X X.X X X X X X.X X.X X X X X X X X X X.X X.X X X.X X X X X X X X X X X X", -".X X.X X X.X X.X X.X}..X}..X}.}. X X X X X X.X X X X}..X.X.X.X}. X X.X X X X X X.X X X.X X X X.X X.X.X X X X X X X X.X X X X X X.X.X.X}..X X X X.X X X X.X X X.X X X X X.X.X.X}.}..X}..X.X}..X}. X X X X X X X X X.X X X X X.X.X X X X X.X X X X X.X X.X X X X X X X X X X X X X X X X X X X X X X X X X.X X X X X X.X X X X.X.X X X.X X X X X X X X X X X X.X X X X X X X X X X X X X X.X X X X X X X X X X.X X X X X X X X X X X X X X X X X.X X X X X X X.X X X X X X.X X X X X.X X.X X X X X X X X X X X X X X X X X X.X X X.X X X X.X X X.X X X X X.X.X.X}. X X X X.X X X X.X X X X X X X X X X X X X X X X X X X X X X.X X X X X X X X X X X X.X X X X X X X X X X.X X X.X X.X}..X}..X}..X X X X X X X.X X X X X X X X X X X X X X X X X X X X X X X X X.X X X X X X X X X X X X.X X X X X.X.X'..X.X.X.X'. X X X X.X X X X.X X X X X X X X X X X X.X X X X.X X X X.X.X.X.X}. X X}. X}. X X X.X X.X.X X X X.X.X.X}.}.}..X}. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X.X X.X X X.X X X.X X X.X.X X X X X X X X.X X X X X X", -" X X X}. X X X X X X X X.X}. X X X X X X X X X X X X X X X X.X}. X X X X X X X X X X}. X X X X X X X}. X X X X X X X X X X X X X}..X}..X X X X X X X X X X X}. X}..X}..X}.}..X}..X}..X}. X X X X X X X X X X X X X}. X X X X}..X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X}..X}.}..X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X}. X}..X}..X}.}..X}. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X}. X X X X X X X.X}..X}. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X'..X.X.X.X'..X.X X X X X X X X X X X X X X X X X X X X X X X X X}..X}..X}.}.}.}..X X X.X X X X X}. X X}.}. X X X}..X}..X.X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X}..X}.}. X X}. X X X}. X X X X X X X X X X X X X", -"}. X}. X}. X}.}. X X X X X X}. X}. X X}.}. X X}. X X}. X}.}.}..X X X X X X X X}. X X}. X}. X X X}. X}..X}.}.}. X X X X X X X}. X}.}.}.}.'. X X X X'.}..X}.}.}. X X X}. X}.}.}..X.X}.}..X X X X X X X X}. X}. X}.}. X X}.}.}. X}. X X X}.}. X}.}. X X}. X X}. X X X X}. X X X X X X}. X X X}. X}. X X}. X X X X X}.}. X X X}..X}.}. X X}. X X}. X}. X X X}. X X}. X X X}. X X X X X}. X X X X X X X X}. X}.}.}. X X X X}. X X X X}. X}. X X X}. X}. X X}. X X X X X X X}.}. X}.}. X X}. X X}. X X X}. X}. X}. X}. X X X}. X}. X}. X'.}..X}.}.}. X X X}. X}.}.}..X X}. X}. X X X X X}. X}. X X X}. X X X X}. X}. X X X X X X X X}. X X}. X X}. X X X X X X X}.}. X X X}.}.}.}. X}. X}. X X}..X}.}. X}. X X}.}.}. X X}. X}. X X X X X X X}. X}. X X X X}. X X X X X X X}. X X X X X X X X X}. X X X X X X X'..X'..X}. X}. X X X X X}. X X}. X X X X X X}. X X X}. X}. X}. X X X X X X X.X}.}..X}. X}. X}. X}. X X}..X}.}.}. X}. X X X X X}. X}. X}. X X X}. X}. X X X X X}. X}. X}. X X X}. X}. X X X X X X X X}. X}. X}..X}. X X X}. X}..X}.}.}. X X X X X X}. X}.", -"}. X X}. X X X X'. X}.}.}. X}. X X}.}. X X}.}. X}. X}.}. X}.}.}.}.}.}.}. X}. X}.}. X X}.}. X}.}.}.}. X}..X}. X X}.}.}.}. X}.}. X}. X}..X X X X'. X X}.}.}.}. X X}.}. X X}..X}. X}.}. X}.}.}.}. X X}. X}. X}.}. X X}. X}..X}.}. X X}.}. X X X X X}. X X}.}. X X}. X}.}. X}.}.}.}. X X X}. X}.}. X}. X}.}.}.}.}.}.}. X}.}. X}.}.}. X X}. X X}. X}. X}.}.}. X}. X X X}.}. X X}.}. X X X}.}.}.}.}.}.}. X X}. X.X}. X X}. X}.}.}.}. X X X}. X X}.}. X X}.}. X}.}.}.}. X}.}. X X X X X}. X X}.}. X}. X X X X X X}.}. X X X X}. X}.}. X X X}.}.}.}. X X}.}. X X}..X}. X X}.}. X}.}.}.}.}. X X}. X}.}. X}. X}. X}.}. X}.}.}.}.}. X}.}. X}. X X}.}. X}.}.}.}.}.}. X}. X X X}. X}..X}. X}.}. X X X}.}..X}.}. X X}..X}.}. X X X X}.}.}.}. X X}. X}.}. X}. X}.}. X}.}.}.}.}.}. X}. X}.}.}.}.}.}.}. X X}.}. X}.}.}. X.X'..X'. X X X}.}.}.}.}. X}. X}.}.}.}. X}.}. X X}. X X}. X X X}.}.}.}.}. X}.}.}.}. X X X X X}. X X}.}. X}.}.}..X}. X}.}. X}.}. X X}.}. X X}. X}. X}.}.}. X}. X}. X}.}. X X}.}. X X}.}.}.}.}.}.}.}. X X}.}..X X}.}. X}.}.}.}. X}.}. X X}.}.}.}.}. X X X X", -"}. X X X X}.}.}.}.}. X}. X}. X}. X X X X X X X}.}.}. X}.}. X X X X}.}. X X}.}. X X}.}. X X}.}.}. X}..X}.}. X}. X X}. X}.}. X X}. X}. X X X X X X X}. X}..X}.}.}. X}. X}.}.}. X}.}.}.}. X}. X X X X}.}. X}. X X}.}.}.}..X X}. X}. X}. X}. X}. X}. X X}.}. X X X}.}. X X}.}. X}. X}. X}. X}. X X}.}. X X}. X X X X X}..X}.}.}.}. X}. X}. X X}.}.}.}. X X}. X}. X}.}. X X X}. X X}.}.}. X X X X X}. X}.}. X}.}. X}.}. X}. X}. X}. X}. X X}.}. X X}. X X X X X}. X}. X}. X}. X}. X}. X X}.}. X X X}. X X}. X X}. X}. X}.}. X X}.}. X X}. X}..X}.}.}. X}. X}.}.}. X}. X}.}. X X}.}. X}. X}. X}. X X X}. X X}. X X}. X}. X}. X}. X X}. X}.}. X X}. X}. X}. X X X X}.}.}. X}. X}.}. X X X}. X X X X}.}.}. X.X}.}.}. X}. X X}. X}. X X}.}. X X X X X X}. X}. X X X X X}. X}.}. X X}.}. X X}. X}. X X}.}.}. X X X'. X.X'. X}.}.}.}..X}. X}. X}. X X}. X X}. X X}.}. X X}.}.}.}.}.}. X}. X}. X}.}.}. X}.}.}.}. X}.}. X X X}.}.}. X X}. X X X}.}. X X}.}. X}. X}. X}.}.}.}. X X}. X X}. X}.}. X X}. X}. X}.}. X}. X}. X}.}. X}.}. X X}. X}. X}..X}. X X}. X X}. X}. X X}. X", -"}.}.}. X}. X}.}.}.}.}.}.}. X'. X}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}.}.}.'. X}. X X}.}.}.}.}.}.}. X X X}.}.}.}.}.}.}.}.}.}.}.}.'. X}.}.}.}. X}.}. X}.}.}.}.}.}.}. X}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}..X}.}.}.}.}. X}.}. X}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}. X}.}.}.}.}.}.}. X X X}.}.}.}.}.}.}. X}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}.}.}.}.}. X}.}. X}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}. X}.}.}.}. X X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}. X}.}.}.}.}.}.}. X}.}.'. X X.X'. X}. X}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X X}.}.}.}. X}.}. X}.}.}.}.}.}. X X}.}.}.}.}.}. X X}.}.}.}. X}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.", -"}.}.}.}.}.}.}.}.'. X X'. X'. X X}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}. X X'. X'. X X'.}.}.}.}.}.}.}.}.}.}.}.}.'. X}.}.'.}.}.}. X X'. X}.}.}.}.}.}.}.}.}.}.}.}.}.'. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}. X X}.}. X}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}..X X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X}.}.}.}.}. X'.}.}.}.}.}.}.}.}.}.}.}. X}.}.}. X}.}. X X X X X}. X}.}. X X}. X X}.}.}.}.}.}.}.}.}.}.}.}. X'. X}.}.'. X}.}.'. X}.}. X'.}.}.}.}.}.}.}.}.}.}.}.}.}. X'. X X'. X'. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}. X'. X'.}.}.}.}.'.}.}.}.}.}.`.}.}.}.}.}.}.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.", -"}.}.}.}.'.}.}.}. X'.'. X'. X'. X}.}.'.}.}.}.}.'.'. X'.}.'.}. X'.}.}.}.}.}.}.}.}.'.}.}.}.}.'.}.}.}.}.'.}.}.}.}.}.}.}.}.}.}.'.}.}.'. X X'. X'. X'.}.}.}.'.'.}.}.}.}.}.}.}. X'.'. X}.}. X'.'. X X'.}.}.}.}.}.'.}.}. X'.'. X}.}.'. X}.}.}.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.}.}.}.}.}.}.'.}.'.}.}.'.b.v.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.v.b.c.c.c.(.'. X'.}.}.}. X'.}.V.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.C.}.}.}.}.(.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.v.b.c.c.c.c.V.}.'.}.}.}.}.'.}.}. Xv.c.c.c.c.b.%.c.c.c.c.b.%.c.c.c.c.c.c.c.V.'.}.}.'.}.}.}.(.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.V.}.'. X'. X}.'..XP.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.b.c.V.V.V.M.C.C.C.C.L.L.L.P.(.(.).}.'.}.}.}.}.}. X}.'.}.}.'. X'. X'. X X'. X'.'. X'.'. X X}.}.}.'.}.}.}.}.`.}.}.}.'. X'. X X'. X'.'.}.}.}.}.'.}.}.}.}.}.}.}.}.'.}.}.}.}.'.'. X'. X}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.'.}.}.}.}.}.'.}.}.}.}.'.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.}.}.'.}.}.", -"}.}.'.}.'.}.'.}.'. X X'. X X'.'.}.}.}.}.}.}.}.}. X'. X'. X X'.}.}.}.}.}.}.}.}.}.'.}.'.}.}.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.}.}. X'.'. X'.'. X X'.}.}.}.}.}.}.'.}.}.}.}.'. X X'. X'.'. X X'.'. X}.}.}.'.}.}.}.'.}.}.'.}.}. X}.'.}.}.}. (.'.}.}.).}.}.'.}.}.}.P. P. X'.}.}.'. X'. X}.O d X}.}.}.}.. % }.}.}.}.'.}.}.}.'.(. V }.}.}.}.}.}.}.V. . : }.}.'.'.}.}. X'.V. : 8 c N $.V.L.).'.}.'. X'.'. X'. X'. X'. X X'.}.}. X'.'.}.}.}.}.}.}.}.}.}.}.}. X'.'. X'.'. X X}.}.}.'.}.}.}.'.}.}.}.}.}.}.}.}.'. X}.'. X'.'. X}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.'.}.}.}.}.}.}.}.}.}.'.}.'.}.'.}.}.}.}.}.}.}.}.}.'.}.}.'.}.}.}.}.}.}.}.}.}.'.}.}.}.}.'.}.}.}.}.}.", -"}.}.}.'.}.}.}.'. X'.'. X'.'. X'.}.'.'.}.'.'.}.'.'.}.'. X'.'. X'.`.}.}.}.`.}.}.'.}.}.'.}.}.}.'.}.}.'.}.'.}.}.}.}.}.'.}.'.}.'.}.'.'.'. X'.'. X'.'.}.'.}.'.}.'.}.}.'.}.'.'. X'.'. X'. X'.'.'.'. X'.}.}.'.}.'.}.'.}.}.'.}.}.'.'.'.}.}.}.}. L.}.}.}.}.}.'.}.}.'.}.C.. P.'.}.'.}.}.'.}.'.}.+ 8 }.}.}.}.}.6 (.}.'.}.'.}.'.}.}.V. b.'.}.}.'.'.}.}.V. : }.}.'.}.}.'.}.'.M. 6 b.(.'. X'.'.'.}.'.'. X'.'. X}.'.'.}.}.'.}.'.}.}.}.}.`.}.}.`.'. X'.'.'. X'.'.}.'.}.'.}.'.}.}.'.'.}.}.'.}.'.}. X'.'. X'. X'.'.'.}.'.}.}.'.}.}.}.'.}.}.}.}.`.}.}.'.'.}.}.'.}.'.}.'.}.}.}.}.}.}.`.}.}.}.}.'.}.}.}.}.'.}.'.}.'.}.}.'.}.'.}.}.}.'.}.}.}.'.}.'.}.'.", -"}.'.}.'.'.'.}.'. X'.'.'.'.'.'. X'.}.'.'.'.'.'.}.'.'.}.'.}.'.}.'.}.'.}.'.}.'.'.}.'.'.}.'.}.'.}.'.'.}.'.}.}.'.'.'.}.'.}.'.`.}.}.'.'.'.'.'.'. X'.'.'.}.'.}.'.'.}.'.'.}.'.}.'.'.}.'.'.'. X'.'.'. X'.'.}.'.'.'.}.'.'.}.'.'.}.'.'.'.'.}.'.}. v.'.}.'.'.}.'.'.}.'.}.c. P.'.'.}.'.'.}.}.'.'.# 6 '.}.}.}.`.Z C.'.}.'.'.'.'.}.'.Z L.}.}.'.'.}.'.}.N. : }.'.}.'.}.'.}.'.M. c P. X'.'. X'.'.'.'.'.'.'. X'.'.'.}.'.}.'.}.'.}.}.'.}.`.'.'.'. X'. X'.}.'.}.'.'.}.'.}.'.}.'.'.}.'.}.'.'.'.'.'. X'.'.'. X`.}.}.}.'.}.'.}.}.'.}.'.}.'.'.}.'.}.'.}.'.}.'.}.}.'.'.'.'.}.}.'.}.'.}.'.'.}.}.'.'.'.}.'.}.'.}.'.'.}.'.}.'.'.}.}.'.}.'.}.`.}.}.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.'.'.'.'.'.'.'.'.'.}.'.'.'.'.'.'.}.'.'.'.'.'.'.'.'.'.'.'.}.).'.'.'.}.'.'.'.'.}.`.'.'.'.'.'. X'.'.'.'.'.'.'.'.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.'.'.'.'.'.'.}.'.'.'.'.}. Z '.'.'.'.'.'.'.'.'.}.Z X P.'.'.'.'.'.'.'.'.'.X a '.'.`.}.}.B. Z '.'.'.'.'.'.'.'.c . '.'.'.'.'.'.'.}.V. : }.'.'.'.'.'.'.'.M. X Z '.'.'.'.'.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.'.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.}.`.`.'.'.}.`.'.'.'.'.'.}.'.'.'.'.'.'.'.'.'.'.'.'.'.}.'.'.'.'.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.`.'.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.`.}.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`. c '.'.'.'.'.'.'.'.'.'.b L.'.'.'.'.'.'.'.'.'.+ 6 '.'.'.'.`.P. b '.'.'.'.'.'.'.).# 6 '.`.}.'.'.'.'.}.V. : '.'.'.'.'.'.'.'.M. c (.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.`.}.`.}.`.}.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.`.}.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}. 2 '.'.'.'.'.'.'.'.'.'.8 X P.'.'.'.'.'.'.'.'.'.+ 6 '.'.'.'.}.}.% % '.'.'.'.'.'.'.(. V '.'.`.'.'.'.'.}.V. : '.'.'.'.'.'.'.'.M. 6 ).'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.}.`.}.`.}.`.}.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.}.).'.'.'.'.'.'.'.'.'.'.'.'.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.`.}.}.`.`.}.`.}.}.`.}.}.`.}.`.}.`.`.}.`.}.`.}.}.`.`.`.}.`.`.}.`.}.`.}.}.`.}.}.`.`.`.}.`.}.`.}.'.'.'.'.`.'.'.`.}.}.`.'.}.`.}.}.}.`.`.}.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.`.}.`.}.`. . '.'.}.`.}.}.`.`.'.).$ P.'.'.'.'.`.'.'.'.`.+ 8 }.'.}.`.}.}.d (.'.'.'.'.'.'.B. v.'.`.}.'.'.'.`.'.V. : }.`.'.}.`.`.`.}.M. d '.}.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.`.`.}.`.}.`.}.}.`.`.}.'.`.`.}.`.}.`.}.}.`.`.`.}.`.`.}.`.}.`.}.'.`.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.'.'.'.'.'.'.'.`.'.'.'.'.`.'.'.'.'.", -"`.'.'.`.'.'.`.'.`.'.'.'.`.'.`.'.'.'.`.`.`.}.`.`.`.`.`.`.`.`.`.`.`.}.`.`.}.`.`.`.`.`.}.}.`.}.`.`.`.`.`.`.`.`.`.`.}.`.}.`.`.`.`.`.`.'.`.'.'.`.'.'.`.`.'.`.`.'.`.`.`.`.}.`.`.`.'.`.`.'.`.`.`.'.`.`.'.'.'.'.`.'.`.'.`.'.`.'.`.'.`.`.}.`.`. P.).`.'.`.`.`.'.'.). P.`.'.`.'.`.'.'.`.}.+ 6 `.'.`.`.`.`.$. C.'.`.'.`.'.`.Z P.'.`.}.'.'.'.'.`.V. : '.'.`.`.}.}.`.}.:. $.}.`.'.`.`.'.'.'.'.'.'.`.'.'.`.'.'.'.`.'.`.'.'.`.'.'.`.'.'._.'.`.'.'.'.`.'.}.}.`.`.}.`.`.'.`.`.}.`.`.}.`.`.`.`.`.`.`.}.}.`.}.`.}.`.`.`.`.`.'.'.`.'.`.`.'.'.`.'.'.`.`.'.`.'.`.`.'.'.`.'.`.'.'.`.'.'.`.`.'.'.`.'.'.`.'.'.'.`.'.`.'.'.'.`.'.'.", -"'.`.`.'.`.`.`.`.`.'._._.`.`.`.'.`.`.'.`.`.'.`.`.`.`.`.`.`.}.`.`.`.`.}.`.`.`.}.`.`.`.`.`.`.`.`.`.`.`.`.`.}.`.`.`.`.`.`.`.`.`.`.`.`.'.`.'.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.'.`.'.`.'.`.`.`.'.`.'.`.'.`.'.`.`.`.`.'.`.'.`.'.'.`.`.`.}.`.'.`. C.'.`.`.`.`.`.}.`.P. P.'.`.`.`.`.`.'.'.`.+ 6 '.`.`.}.`.`.C. $.'.'.'.`.`.'.d O `.'.`.`.`.`.`.`.'.B. : `.`.`.`.`.`.}.`.M. C.`.'.`.'.'.`.`.'.'.`.`.'.`.`.`.`.'.`.`.`.'.`.`.`.`.`.'.`.`.`.`.'.'._._.'.`.`.}.`.`.`.`.`.`.`.`.`.`.'.`.`.`.`.`.`.`.`.}.`.`.`.`.`.`.`.`.`.`.`.'.`.'.'.`.`.`.'.`.`.'.`.`.`.`.'.'.`.`.'.'.`.`.`.'.`.'.`.`.`.`.`.`.`.'.`.`.'.`.`.`.`.`.'.`.`.", -"`.`.'.`.'.`.'.`.'.`.'.'.`.}.`.`.'.`.`.`.`.`.`.}.`.`.}.`.`.'.`.`.`.`.`.`.`.`.`.`.}.`.`.}.`.`.}.`.`.`.}.`.`.`.`.}.`.`.}.`.`.`.}.`.`.'.`.`.`.'.'.`.`.`.}.`.'.`.`.`.}.`.`.'.`.`.`.`.`.'.`.'.`.`.'.`.`.`.`.'.'.`.`.`.`.`.`.`.}.`.`.`.`.'.`. %.}.`.'.}.`.`.`.`.C. P.`.`.'.'.'.`.`.`.`.+ a '.`.`.`.`.`.(. b '.'.`.'.'.).O 6 `.`.`.'.`.'.'.`.'.B. : `.`.'.'.`.`.`.`.:. 8 `.`.`.'.`.'.`.`.`.`.'.`.`.'.'.`.`.`.'.`.`.`.`.`.'.`.`.'.'.'.`.`.`.'.'.'.`.`.`.`.`.`.`.`.`.`.`.}.`.`.`.`.`.`.`.}.`.`.`.`.`.`.}.`.`.`.`.}.'.`.`.`.`.`.'.`.`.`.`.'.`.`.'.`.`.`.`.`.'.`.`.`.'.`.`.`.'.`.'.`.'.'.`.'.`.'.`.`.`.'.'.`.'.`.`.'.", -"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`._.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`. V `.`.`.`.`.`.`.`.%. P.`.`.`.`.`.`.`.`.`.+ 6 `.`.`.`.`.`.'.2 : _.`.`.`.`.P. C `.`.`.`.'._.'._._.N. : `._.'._.'.`.`.`.M. C.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.'.`.'._.'._.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.", -"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`. d `.`.`.`.`.`.`.).Z P.`.`.`.`.`.`.`.`.).+ 6 `.`.`.`.`.`._.b (.`.`.`.`.M. M.`.`.`.`._.'._.'.`.B. : `.`.`.`.`.`.`.`.:. b `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`._._.'.`.`._.'.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`._.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.", -"`.`._._.`.`._._._.`._.`.`._._.`.`._.`.`.`.`.`.`.`.`.`._.`.`.`.`._.`.`._._.`.`._.`.`._.`.`._.`.`.`.`._._.`.`._._._.`._.`.`.`.`._.`._.`._._.`.`.`.`.`.`.`.`._.`.`.`.`.`._._.`.`._.`.`.`.`.`._._.`.`.`.`.`._.`.`.`.`.^.`.`.`.`.`.`.`.`.`. : _.`._.`.`.`.`.`.b L.`._._.`._.`.`.`.`.+ 6 `.`._._.`.`.`.%. C.`._._.`.C P._.`.`.`._.`._._._.B. : `._.`.'._.`._.`.:. ~._.`.`.`._.`._._.`._.`._._.`._.`.`.`.`._._.`._.`.`.`._._.`._._._._._.`._.`.`.`._.^.`.`.`.`.`.`.`.`.`.`.`.`._.`.`._.`._.`.`.`.`._.`.`.`.`.`.`.`._._.`.`.`.`.`.`.`.`.`.`._.`.`._.`.`.`._.`.`._.`._._.`.`._.`.`._.`.`._._.`._.`.`._._.`.", -"_.`.`.`.`._.`.`.`._.`.`._.`._.`._.`._._.`._.^.`.`.`._.`.`._.^.`.`._.`.`.`.`._.`._._.`._._.`._._._.`.`.`.`._.`.`._.`.`.`._._.`.`.`._.`.`._.`._.`.`.`.`.^.`.`.`._.`.^.`.`.`.`._.`._._.`.`.`._.`.`.`._._.`.`._._.`.`.`.`.`.^._.`._.`.`.`. _.`._.`._.^.`.`.4 P.`._.`.`._.`._.`.`.+ 6 `.`.`.`._.`._.L. $.`._.`.`.6 + _.`._._.`._.`.'._.`.B. : `.'._._.`._.`._.M. v.`.`._.`.`._.`.`._.`._.`.`._.`.`.`.`.`._.`.`._.`._.`.`.`._.`._.'.'._.`.`.`.`.`.`.`.`._.`.`.`._.`._.`.`._._.`._.`.`._.`._._.`._.`.`._._.`._._.`.`.`.`.`._._.`.`._._.`.`.`.`._.`.`._._.`.`._.`.`._.`.`._.`.`._.`._._.`.`._.`.`._.`._.`.", -"`.`._._._.`.`._._._.`._._.`._._.`._._.`.^.`.`.`.^.`._.`._.`._.`._._._.`._.`._.`.`._.`._.`._._.`.`._.`._._.`._._.`._._.`._.`._.`.`._.`._.`._._.`.`._._.`._._._.`._.`.^.`.`._.`._._._.`._.`._.`._._.`._.`._._.`._.`.^._.`._._.`._.`._.`. K.`.`._.`._.`.`.+ K.`._._.`._._.`._.`.+ 6 _._.`._.`._._.~.. b `._.`._.. d _.`.`.`._._._.`._.`.N. : _._._._._.^.`.`.M. N _._._.`._._.`._.`._._.`._.`._._.`._._._.`._.`._.`._.`._.`._._.`._.`.^.`._._._.`._.`.`._.`.`.^.`.^.`._.`._._.`._.`._._._._.`._.`._._._.`._.`._.`._._._._.`._._._.`._._._.`._._.`._._._.`._.`._.`._._._.`._._.`._.`._._._.`._._._.`._.", -"_._._._._._._._._._._._._._._._._._._._.^.`.^.`.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.`.`.^.`._.^.`._._._._._._._._._._._._._._._._._.`._.`.`.^._._._._._._._. B.^.`._._._._.~. K._._._._._._._._._.O d _._._._._._._._.8 : _._.`.K. Z _.^.`.^.`._.`._._._.N. : _._._._._.`.`.^.:. X + : _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.`.^._._._._._._._._.^.`._._.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.", -"_._._._._._._._._._._._._._._._._._._.`.`.^.`._.^.`._._._._._._._._._._._._._._._.^._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.`.^.^.`.^._._.`._._._._._._._._._._._._._._._._._.^.^.^.`.`._._._._._._.`. $.`._._.^.^.`.K. P.^.`._._._._._._._.O 6 _._._._._._._._.V ~._._.:. N._.`.^.^._._._._._._.N. : _._._._._.`.^.`.>. N._._.K.%.2 ).`._._._._._._._._._.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.^._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.", -"_._._._._._._._._._._._._._._._._._._.^.^.`.^.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.^._._._._._._._._._._._._.^.`.`.^.`._.^.^._._._._._._._._._._._._._._._._._.`.`._.^.`.^._._._._._._. N _._.^.`.`.^.B. K._.`.^.`._._._._._.O 6 _._._._._._._._.:. C._.`.V P._.^.`.`._._._._._._.N. : `._._._._.^.`.^.M. N._._.`.`.~.b K.~._._._._._._._._._.^.^.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.`._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.", -"^._._._._._.^._._._._._._._._._.`.^.`.`.^.`.^._.^._._._._._._._._._.^._.^._._._._.^._._.^._._._.^._._._._._._._._._._._.^._._._._._._._._._._._.^._._._._.^._._.`.^._._.`.`.^._._.^._._.^._._._._._._._._._._._._._.^._._._._.^._._._. 6 ^._.`.`.^._.%. K._._._._._._.^._._.O 6 ^.`._._.^._._._.P. $._._.5 $ `.^.`.^._._._.^._._._.N. 5 b b b b b b b b b b b b b b b C ^._._._._._._._.:. N.~._.^._._.~.+ >._._._.^._._.^._._.^._._._._.^._._._.^._._.^._._._._._._._._._._.^._._.^._.^._._.^.`.^._._.^.`.^._.^._._._._._.^._._._._._._._._._._._._._._._.^._._._._._._._._._._._.^._._._._._._._._._._._.^._._._._.^._._.^._._._.^._._._._._.", -"_.^.^.^._.^._.^.^.^._.^.^._.^.^.^.^.^.^.^.^._._._.^.^.^._.^.^.^.^.^._._._.^._.^._._.^._._._.^._._.^._.^.^._.^._.^.^.^._._.^.^.^.^._.^._.^.^.^._._.^.^.^._._.^._.^._.^._.^.^._.^._._.^._._._.^.^.^.^._.^.^._.^.^.^.^._._.^._.^._.^._.^. $ _._.^.^._.^.V P.^._.^.^.^.^._._.^.# 5 ^.^._.^._.^.^.^.^.+ b _.~.O d ^._._.^.^.`.^._.^._.^.N. %._.^.^.^._._._._._._.^._._._.^._._.^.^.^._.^.^._.:. N.^._._._.^.^.V $._.^._.^._._.^._.^._._.^.^.^._._.^._._.^._._._.^._.^.^._.^.^._.^._.^.^._._.^._.^._.^._.^._._.^._._._.^._.^._._._.^.^.^._.^.^._.^.^._.^.^.^.^.^._._._.^._.^._.^.^.^.^.^._._._.^.^.^.^._.^.^.^.^._._.^._.^._._.^._.^.^.^._._._.^.^.^.", -"^._._.^.^._._.^.^._.^._._.^._.^.^.`.^._._.^.^._.^._._.^.^._._.^._.^._.^.^._.^.^.^.^.^._.^.^.^.^.^._.^.^._.^.^._._.^._.^.^._._.^._.^.^._._.^._.^.^._._.^.^.^.^._.^.^._.^.^._.^.^.^.^.^.^.^.^.^._.^.^.^.^._.^._.^.^._._.^._.^.^._._.^._. W._.^._.^.^.b K._.^._.^.^._._.^.^.+ 6 ^._.^._.^.^.^.^.^.d 2 ^.K. { ^.^.^.^._.^.^._.^._.^.N. %._._.^._.^.^.^._.^.^.^._.^.^.^._.^._.^._.^._.^._.:. N.^.^.^.^.^._.%. C ^._.^.^._.^._.^.^.^.^.^._.^.^.^.^.^.^.^._.^.^.^.^.^._.^.^._.^.^._.^._._.^.^._.^._._.^.^._.^.^._.^.^._.^.^.^.^._.^.^._.^._._.^._.^.^._._.^._.^._.^.^._.^.^.^._._.^._.^._.^.^._._.^._.^._.^.^._._.^._.^.^._.^._._.^.^._.^._.^._._.^.", -"^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^._.^.^.^.^.^._.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^._.^.^.^.^.^.^.^.^.^.^.^._.^.^._.^.^._.^.^._.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^. K.^.^.^.^.^.> K.^.^.^.^.^.^.^.^.^.O 6 ^.^.^._.^._.^.^.^.Z Q.%. N.^._.^.^.^.^.^.^.^.^.^.N. %.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.:. >.^.^.^.^.^.^.C. V ^.^.^.^.^.^._.^._.^.^.^._.^._.^.^._.^.^.^.^.^._.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.", -"^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^._.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^. :.^.^.^.^.^.+ K.^.^.^.^.^.^.^.^.^.O 6 ^.^.^.^.^.^.^.^.^.>. C.V W._.^.^.^.^.^.^.^.^.^.^.N. %.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.:. >.^.^.^.^.^.^.H. b ^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^._.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.", -"^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^. $.^.^.^.^.W. K.^.^.^.^.^.^.^.^.^.O 5 ^.^.^.^.^.^.^.^.^.W. %.4 $ ^.^.^.^.^.^.^.^.^.^.^.^.>. %.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.:. N.^.^.^.^.^.^.K. f ^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.", -"^.^.^.^.^.^.^.^.^.^.^.!.^.^.!.^.!.^.^.^.^.!.!.^.^.^.!.^.!.^.^.^.^.!.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.!.^.^.!.^.!.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^. B ^.!.^.^.H. K.^.^.!.^.!.^.^.^.^.O 5 ^.!.^.!.^.^.^.^.^.^.$ b b ^.^.!.^.^.!.^.^.^.^.^.^.>. %.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.!.!.^.^.^.^.^.^.;. >.^.^.!.^.^.^.J. d ^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.!.^.^.!.^.!.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.", -"^.^.^.!.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.!.^.^.!.^.^.^.!.^.^.^.^.^.^.!.^.^.!.^.!.^.!.^.!.^.^.!.^.!.^.^.!.^.^.^.^.^.^.!.^.!.^.!.^.!.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.!.^.!.^.!.^.^.^.!.^.^.^.^.!.^.^.^.!.^.^.^.^. 5 ^.^.^.^.>. J.^.^.^.^.^.^.^.!.^.O 5 ^.^.^.^.^.^.^.!.^.^.b . { ^.^.^.!.^.^.^.^.!.^.^.^.>. =.!.^.^.!.^.^.^.^.!.^.!.^.!.^.^.^.^.^.^.^.^.!.^.^.:. >.^.^.^.^.^.^.K. a ^.^.!.^.^.^.!.^.!.^.!.^.!.!.^.!.^.^.^.!.^.^.^.!.^.^.^.^.^.^.!.^.^.!.^.!.^.!.^.!.^.^.!.^.!.^.^.!.^.^.^.^.^.^.!.^.!.^.!.^.!.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.!.^.!.^.!.^.^.^.!.^.^.^.^.!.^.^.^.!.^.!.^.!.^.^.^.!.^.^.^.!.^.!.^.!.^.", -"^.^.^.^.!.^.^.^.^.!.^.^.!.^.^.^.^.^.^.!.^.^.^.^.!.^.^.^.^.^.!.^.^.^.!.^.^.!.!.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.!.^.^.!.^.^.!.!.^.^.^.^.^.^.^.^.^.!.^.^.^.!.!.^.^.!.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.!.^.^.^.!.^.^.^.^.^.^.!.^. $ ^.^.!.^.%. K.^.^.^.^.^.^.!.^.^.O 5 ^.^.^.^.^.^.!.^.^.!.$. N.^.^.!.^.!.^.^.^.^.!.^.^.>. %.^.^.^.^.!.^.^.^.^.^.^.!.^.^.^.!.^.!.^.^.^.^.^.^.:. >.^.^.^.^.^.^.K. d ^.^.!.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.!.^.^.!.!.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.!.^.^.!.^.^.!.!.^.^.^.^.^.^.^.^.^.!.^.^.^.!.!.^.^.!.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.!.^.^.^.!.^.^.^.^.^.^.^.^.^.!.^.!.^.!.^.!.^.^.^.^.!.", -"!.^.!.^.^.!.^.!.^.^.!.^.^.^.!.^.^.!.^.!.^.!.!.^.^.^.!.^.!.^.!.^.^.!.^.!.^.^.^.^.^.!.!.^.!.^.^.^.!.^.!.^.^.!.!.^.^.!.^.^.^.^.^.^.^.!.!.^.^.!.^.!.^.^.!.^.^.^.^.!.^.^.^.!.!.!.^.^.^.!.!.^.^.!.!.^.!.^.!.!.^.^.^.!.^.!.^.!.!.^.!.^.!.^.^. Q.^.^.^.B K.!.^.!.^.!.^.!.^.^.O d ^.^.!.^.!.^.!.^.^.^.H. Q.^.!.^.^.^.^.!.!.^.^.!.^.>. %.^.!.^.!.^.^.!.!.^.!.^.^.!.^.!.^.!.^.!.^.!.!.^.!.;. >.^.^.!.!.^.!.J. f !.!.^.^.!.^.^.^.!.^.^.!.^.^.!.^.!.^.!.^.!.^.^.^.^.^.!.!.^.!.^.^.^.!.^.!.^.^.!.!.^.^.!.^.^.^.^.^.^.^.!.!.^.^.!.^.!.^.^.!.^.^.^.^.!.^.^.^.!.!.!.^.^.^.!.!.^.^.!.!.^.!.^.!.!.^.^.^.!.^.!.^.!.!.^.!.^.^.!.!.^.!.^.^.^.^.^.^.^.^.!.!.^.", -"^.!.^.!.!.^.!.!.^.!.!.^.!.^.^.!.!.^.!.^.!.!.^.^.!.^.^.!.!.^.!.^.!.^.^.!.!.^.!.^.!.!.^.^.^.^.!.!.^.!.^.!.!.^.^.!.^.^.!.^.!.!.^.!.!.!.^.^.!.!.^.^.!.^.^.!.^.!.!.^.^.!.!.^.^.!.^.!.!.!.^.^.!.!.^.^.!.^.!.^.^.!.!.^.!.^.^.!.!.^.^.!.^.^.!. J.^.!.!.d J.!.^.^.!.!.^.^.!.^.O 5 !.^.^.!.^.!.!.^.!.!.Q.. : !.^.^.!.^.!.^.^.!.^.!.^.^.>. %.^.!.^.^.!.!.^.^.^.^.!.!.^.!.^.^.!.!.^.!.^.^.!.^.;. >.!.!.^.!.^.^.J. f ^.^.^.!.^.!.!.^.^.!.^.^.!.^.!.!.^.!.^.^.!.!.^.!.^.!.!.^.^.^.^.!.!.^.!.^.!.!.^.^.!.^.^.!.^.!.!.^.!.!.!.^.^.!.!.^.^.!.^.^.!.^.!.!.^.^.!.!.^.^.!.^.!.!.!.^.^.!.!.^.^.!.^.!.^.^.!.!.^.!.^.^.!.!.^.^.!.!.!.^.^.^.^.!.!.!.^.^.!.!.^.^.!.", -"^.!.!.!.^.!.!.^.!.!.^.!.!.!.!.!.!.!.^.!.!.^.!.!.!.!.!.^.!.!.^.!.^.!.!.^.!.!.!.^.!.^.!.!.!.!.!.^.^.!.!.!.^.!.!.^.!.!.^.!.!.^.!.!.!.^.!.!.!.^.!.!.!.!.!.!.!.^.!.!.!.^.!.!.^.!.!.^.!.^.!.!.!.^.!.!.^.!.^.!.!.^.!.!.^.!.!.^.!.!.!.!.!.!.!. >.!.^.!.2 J.!.!.!.^.!.!.^.!.!.+ 5 !.!.^.!.!.!.^.!.!.^.!.> b !.!.^.!.!.!.!.!.!.!.^.!.!.N. %.!.!.!.!.^.^.!.!.!.!.^.!.!.^.!.!.^.!.!.^.!.!.^.!.;. >.^.!.!.^.!.!.H. b ^.!.!.^.!.!.^.!.!.!.!.!.!.!.^.!.!.^.!.!.^.!.!.!.^.!.^.!.!.!.!.!.^.^.!.!.!.^.!.!.^.!.!.^.!.!.^.!.!.!.^.!.!.!.^.!.!.!.!.!.!.!.^.!.!.!.^.!.!.^.!.!.^.!.^.!.!.!.^.!.!.^.!.^.!.!.^.!.!.^.!.!.^.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.^.!.!.^.!.", -"!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.^.!.^.!.!.!.!.!.^.!.!.^.!.^.!.!.!.^.!.^.!.^.^.!.^.!.^.!.^.!.!.!.!.^.!.!.!.^.!.^.!.^.!.!.!.!.^.^.^.!.!.!.!.^.!.!.!.^.!.!.^.!.^.!.!.^.!.!.!.^.!.!.!.^.!.^.^.!.!.!.!.^.!.!.!.!.^.^.!.^.!.!.!.!.^.^.^.!.^. $.!.^.!.+ J.^.!.^.!.^.!.^.!.^.O 5 !.!.!.^.!.^.^.!.^.!.!.B ..!.^.!.^.!.^.^.!.^.!.!.^.!.>. %.!.^.!.!.^.!.^.!.^.^.!.!.!.!.^.!.!.^.!.!.^.!.^.!.;. >.^.!.!.^.!.^.C. B !.!.^.^.!.^.!.!.!.^.!.!.^.!.^.!.^.^.!.!.^.!.^.^.!.^.!.^.!.^.!.!.!.!.^.!.!.!.^.!.^.!.^.!.!.!.!.^.^.^.!.!.!.!.^.!.!.!.^.!.!.^.!.^.!.!.^.!.!.!.^.!.!.!.^.!.^.^.!.!.!.!.^.!.!.!.!.^.^.!.^.!.!.!.!.^.^.!.^.!.^.^.!.!.!.^.!.!.^.!.^.!.^.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.^.!.!.!.!.!.^.!.!.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.^.!.^.!.!.!.!.^.!.^.!.!.!.!.!.^.^.!.!.!.!.!.!.^.!.!.!.!.!.!.!.!.^.!.!.^.!.!.!.!.!.!.!.^.!.!.!.!.^.!.!.!.!.!.!.!.^.!.!.!.!.!.!.!. N !.!.W. : J.!.!.!.!.!.!.!.!.!.O 5 !.^.!.!.!.^.!.!.!.^.!.%. C.!.!.!.!.!.!.!.!.!.!.!.^.!.>. =.!.!.!.!.^.!.!.!.!.!.!.!.^.!.!.^.!.!.!.!.^.!.!.!.;. >.!.^.!.!.!.!.-. { ^.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.^.!.^.!.!.!.!.^.!.^.!.!.!.!.!.^.^.!.!.!.!.!.!.^.!.!.!.!.!.!.!.!.^.!.!.^.!.!.!.!.!.!.!.^.!.!.!.!.^.!.!.!.!.!.!.!.^.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^. + a !.!.H. a J.!.!.!.!.!.!.!.!.!.+ 5 !.!.!.!.!.!.!.!.!.!.!.H. Q.!.!.!.!.!.!.!.!.!.!.!.!.!.>. %.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.;. >.!.!.!.!.!.!.{ ;.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!. 4 $ !.!.;. B J.!.!.!.!.!.!.!.!.!.+ 5 !.!.!.!.!.!.!.!.!.!.!.!.O > !.!.!.!.!.!.!.!.!.!.!.!.!.!.>. %.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.;. >.E.!.!.!.!.!.f H.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!. b !.!.{ { J.!.!.!.!.!.!.!.!.!.O 5 !.!.!.!.!.!.!.!.!.!.!.!.a b !.!.!.!.!.!.!.!.!.!.!.!.!.!.>. %.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.=. >.!.!.!.!.!.Q.O I.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.E.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.E.!.!.!.!.!.!.E.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.!.!.E.!.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.!.!.E.!.!.E.!.!.!.!.!.!.!.!.E.!.!.E.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.E.!.!.!.!.!.!.!.E.!.!.!.E.!. B @ J.!.B # %. J.!.!.!.!.!.E.!.!.!.+ 5 !.!.E.!.!.!.!.!.E.!.!.E.C ..!.!.!.E.!.!.!.E.!.E.!.!.!.!.>. X.!.E.!.!.!.!.!.!.!.!.!.!.Q.!.!.E.!.!.!.!.E.!.!.!.=. >.!.E.^.!.!.B $ !.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.E.!.E.!.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.!.!.E.!.!.E.!.!.!.!.!.!.!.!.E.!.!.E.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.E.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.E.!.!.E.!.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.E.!.!.!.!.!.E.!.!.!.!.!.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!. N a -.!.a 4 .. J.!.!.!.!.!.!.!.!.Q.O 5 !.!.!.!.!.E.!.!.!.!.!.!.>. H.!.!.!.!.!.!.!.!.!.!.!.!.!.E.>. N =.=.=.%.=.=.=.=.=.=.=.=.=.=.,.!.!.E.!.!.!.!.!.!.=. >.R.K.t.{ < b !.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.E.!.!.!.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.!.E.!.!.!.!.!.E.!.!.!.!.!.!.!.!.E.!.!.!.E.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.E.!.!.!.!.E.!.!.!.!.!.!.!.!.E.", -"!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.!.!.E.!.E.!.!.!.!.E.!.E.!.E.!.!.E.!.E.!.E.!.E.!.!.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.E.!.!.E.E.!.!.!.!.E.E.!.!.!.!.!.E.!.!.!.!.E.!.E.!.E.!.!.E.!.!.!.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.E.!.!. B b ..!.: f . J.!.E.!.E.!.E.!.E.!.O 5 E.!.E.!.!.!.E.!.E.!.!.!.J. Q.E.E.!.!.E.!.E.!.E.!.E.E.!.!.>. < !.E.!.!.!.!.E.!.!.=. =.!.E.!.!.!.E.!.E.!.E.!.E.!.E.!.E.!.!.E.!.!.!.!.E.!.E.!.E.!.!.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.E.!.!.E.E.!.!.!.!.E.E.!.!.!.!.!.E.!.!.!.!.E.E.!.!.E.!.!.E.!.!.!.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.E.!.!.!.E.E.!.!.!.!.E.!.E.!.E.!.!.", -"E.!.!.!.E.!.!.!.!.!.E.!.!.!.E.!.E.!.!.E.!.!.E.!.!.E.E.!.!.!.E.!.E.!.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.!.E.!.!.!.E.!.E.!.!.E.!.!.!.!.E.!.!.E.!.!.!.E.!.!.!.E.!.!.E.!.!.!.!.!.E.!.!.!.E.!.!.E.!.!.!.!.!.E.!.!.!.!.E.E.!.!.!.E.!.!.!.!.!.E. B { V !. C . J.E.!.!.!.E.!.!.!.!.+ 5 !.!.E.!.!.E.!.!.E.!.!.E.!.@ 4 E.!.!.E.!.!.E.!.!.!.!.!.E.!.E.>. < !.!.!.!.!.E.!.!.!.;. R.!.!.E.!.!.!.E.!.!.!.E.!.!.E.!.!.!.E.E.!.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.E.!.!.!.!.E.!.E.!.!.E.!.!.!.!.E.!.!.E.!.!.!.E.!.!.!.E.!.!.E.!.!.!.!.!.E.!.!.!.E.!.!.E.!.!.!.E.!.!.!.E.!.!.!.!.!.E.!.!.!.E.!.!.E.!.!.!.!.E.!.!.!.!.E.!.!.!.E.", -"!.!.E.E.!.!.E.E.E.E.!.!.E.E.!.!.!.E.!.!.E.!.!.E.E.!.!.!.E.!.E.!.!.!.E.!.!.E.E.!.!.E.!.E.!.!.E.!.E.E.!.!.E.E.!.!.!.!.E.E.!.!.E.!.E.!.E.!.!.E.!.E.!.!.E.!.!.E.!.E.!.E.E.!.E.!.!.E.!.!.E.!.E.!.E.!.E.E.!.!.E.E.!.!.!.!.E.E.!.!.E.E.E.!.!. B ;. a I. =. . i.!.!.E.E.!.!.E.E.E.O 5 E.!.!.E.!.E.E.!.E.!.!.E.!.a N !.!.E.!.!.E.!.!.E.!.E.!.!.E.!.>. < E.!.E.!.E.!.!.E.E.=. B !.E.!.!.E.!.E.!.!.E.!.E.!.!.E.!.E.E.!.!.!.E.!.!.E.E.!.!.E.!.E.!.!.E.!.E.E.!.!.E.E.!.!.!.!.E.E.!.!.E.E.E.!.E.!.!.E.!.E.!.!.E.!.!.E.!.E.!.E.E.!.E.!.!.E.!.!.E.!.E.!.E.!.!.!.E.E.!.!.E.E.E.E.!.!.E.E.!.!.E.!.!.E.E.!.!.E.!.E.!.E.!.E.E.!.", -"E.!.E.!.E.E.E.!.!.E.!.E.!.E.!.E.E.!.E.E.E.!.E.!.!.!.E.E.!.E.E.!.!.E.E.!.E.E.!.!.E.!.E.E.!.E.!.E.!.E.!.E.E.!.E.!.E.E.E.!.E.E.!.E.!.!.E.E.E.!.E.E.!.E.!.E.E.E.!.!.E.!.E.E.E.!.E.E.!.E.!.E.E.!.E.E.!.E.!.E.!.E.!.E.E.!.E.!.E.!.E.!.E.!.E. B H. ; t. C. . J.E.!.E.!.E.!.E.!.!.O 5 E.!.E.E.!.!.E.!.E.!.E.!.!.{ %.E.E.E.!.E.!.!.E.E.!.E.!.E.!.!.-. 4 !.E.!.E.E.E.E.E.!.=. ; R.E.!.E.E.!.E.E.!.E.!.E.E.E.!.!.!.E.!.E.!.E.E.!.E.E.!.!.E.!.E.E.!.E.!.E.!.E.!.E.E.!.E.!.E.E.E.!.E.E.E.!.!.!.E.E.E.!.E.E.!.E.!.E.E.E.!.!.E.!.E.E.E.!.E.E.!.E.!.E.E.!.E.E.E.!.E.!.E.!.E.!.!.E.!.E.!.E.!.E.E.!.E.!.E.!.E.!.E.E.!.!.!.E.!.E.", -"E.E.!.E.E.!.!.E.!.E.E.E.!.E.E.!.E.E.!.E.E.!.E.E.E.E.!.E.E.!.E.E.E.E.!.E.!.E.E.E.!.E.E.!.E.E.E.!.E.E.E.!.E.E.E.!.!.E.!.E.E.!.E.E.E.E.E.!.E.E.!.E.E.E.E.!.E.!.E.E.E.E.E.!.E.E.E.!.E.E.E.!.!.E.E.!.!.E.E.!.E.E.E.!.E.E.!.E.E.E.!.E.E.E.!. B R. =. I... J.E.E.!.E.E.E.!.E.E.O 5 !.E.E.!.E.E.!.E.E.E.!.E.E.,. t.E.!.E.E.E.E.E.E.!.E.!.E.E.E.E.-. < E.E.E.E.!.!.E.!.E.=. @ J.E.!.E.E.E.E.!.E.E.E.E.!.!.E.E.E.E.!.E.E.E.E.!.E.!.E.E.E.!.E.E.!.E.E.E.!.!.E.E.!.E.E.E.!.!.E.!.E.E.!.!.E.E.E.E.!.E.E.!.E.E.E.E.!.E.!.E.E.E.E.E.!.E.E.E.!.E.E.E.!.!.E.E.!.E.E.!.E.E.E.!.E.E.E.E.E.!.E.E.!.!.E.E.E.E.!.E.E.E.!.E.E.E.!.E.E.", -"E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.!.!.E.E.E.E.E.!.E.E.E.E.!.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.!.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.!.E.E.!.E.E.E.!.E.E.E.E.E.!.E.!. B T.@ N . E. . i.E.E.E.E.E.E.E.E.E.O 5 E.E.E.E.E.E.E.E.E.E.E.E.!... X.E.E.E.!.E.E.!.E.E.E.E.E.E.E.!.-. < !.E.E.E.E.E.E.E.T.=. f I.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.!.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.!.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.!.", -"E.!.!.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.!.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.!.E.E.!.E.E.E.E.E.!.!.E.E.E.E.E.!.E.E.E.E.E.!.E.!.E.E.!.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.E.E.E. B E.5 % : E. . J.E.!.!.E.E.E.E.!.E.O 5 E.E.!.E.E.E.E.E.!.E.E.!.E.B N E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.-. < !.E.E.E.E.E.!.E.E.=. + f H.T.E.E.E.E.E.!.!.E.E.E.E.E.E.!.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.E.!.!.E.E.!.E.E.E.E.!.E.!.E.E.E.E.E.!.E.E.E.E.E.!.E.!.E.E.!.E.E.E.E.!.E.E.E.E.!.!.E.E.E.E.!.!.E.E.E.E.E.E.E.E.E.!.E.E.E.E.E.E.E.E.E.E.E.E.E.", -"E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E. B E.N a E... i.E.E.E.E.E.E.E.E.E.O 5 E.E.E.E.E.E.E.E.E.E.E.E.E.a $ E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.>. 4 E.E.E.E.E.E.E.E.T.=. > f C t.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.", -"E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.T.E.E.E.E.E.T.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E. l E.{ B E. . J.E.T.E.E.E.E.E.E.E.X 5 E.T.E.E.E.E.E.E.E.E.E.E.E.@ J.T.E.E.E.E.E.E.E.E.E.E.E.E.E.-. > T.E.E.E.E.E.E.E.T.=. ; B ,.R.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.T.E.E.E.E.E.T.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.", -"E.E.E.E.T.T.E.E.E.E.T.T.E.E.E.E.E.E.E.T.E.E.E.T.E.E.E.T.E.E.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.T.E.E.E.T.E.T.E.E.E.T.E.E.E.E.T.E.E.E.T.T.E.E.E.T.E.T.E.E.E.E.E.E.E.E.T.T.E.E.E.T.E.E.E.E.T.E.E.T.E.E.T.E.E.E.E.E.E.E.E.T.E.E.E. B T.-. ..E. . i.E.E.E.E.T.T.E.E.T.# 5 T.E.E.T.T.E.E.E.E.E.E.E.I. =.T.E.E.E.E.E.E.T.E.E.E.T.E.E.-. > E.E.E.T.E.T.E.E.E.=. + B i.E.E.E.E.E.T.E.E.E.T.E.E.E.T.E.E.E.E.E.E.E.T.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.T.E.E.E.E.T.E.E.E.T.E.T.E.E.E.T.E.E.E.E.T.E.E.E.T.T.E.E.E.T.E.T.E.E.E.E.E.E.E.E.T.T.E.E.E.T.E.E.E.E.E.E.E.E.T.T.E.E.T.E.E.E.T.E.T.E.E.T.T.E.E.T.T.E.E.E.E.T.E.E.E.T.", -"T.E.T.E.E.E.E.T.T.E.E.E.T.E.E.E.T.T.E.E.T.T.E.E.E.E.E.E.E.T.E.E.E.E.Y.E.T.E.T.E.E.T.E.E.T.T.E.E.E.E.E.E.E.T.E.E.E.T.E.T.E.E.E.E.E.E.T.E.T.E.E.E.E.T.E.E.E.E.E.E.E.E.T.E.T.E.E.E.E.T.E.E.E.E.T.E.T.E.E.E.E.E.E.E.T.E.E.T.E.T.E.E.E.E.E. l E.i. -.T. . i.T.E.E.E.E.E.E.T.T.O 5 T.E.E.E.E.E.T.E.T.E.E.E.t. f E.E.E.T.E.T.E.E.E.T.E.E.E.T.-. 4 E.T.E.E.E.E.E.E.T.&. d i.R.T.E.T.E.T.E.E.E.T.E.E.E.T.E.T.E.T.E.E.E.E.T.E.E.Y.E.T.E.T.E.E.T.E.E.E.E.E.E.E.E.E.E.E.T.E.E.E.T.E.T.E.E.T.E.E.E.T.E.T.E.E.E.E.T.E.E.E.E.E.E.E.E.T.E.T.E.E.E.E.T.E.E.E.E.T.E.E.T.T.E.E.E.E.T.E.E.T.E.T.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.T.E.E.", -"T.T.E.E.E.E.T.E.T.E.T.T.E.E.T.T.E.T.T.E.E.T.T.E.Y.E.T.E.E.T.T.T.E.T.E.E.T.T.E.E.Y.E.E.T.E.T.E.T.T.E.T.T.E.T.T.T.E.E.T.E.T.E.T.T.E.T.E.T.T.E.T.E.T.E.T.T.E.T.T.T.E.T.E.T.T.E.T.E.T.E.T.E.E.T.E.T.E.E.T.E.T.E.T.T.E.E.E.T.T.T.E.E.T.E.T. B E.U. i.T. . i.E.E.T.E.T.E.T.E.T.# 5 T.E.T.E.E.E.E.T.T.E.T.E.X. ; U.T.T.E.T.E.T.T.E.E.T.T.E.E.-. 4 T.E.E.T.T.E.T.E.T.=. . { T.T.E.T.E.E.T.E.E.T.T.E.E.T.E.T.E.E.T.E.T.E.E.T.E.E.T.T.E.E.T.E.E.T.T.T.E.T.T.E.E.T.E.T.T.T.E.E.T.E.T.E.T.E.E.T.E.T.T.E.T.E.T.E.T.T.E.T.T.T.E.T.E.T.T.E.T.E.T.E.T.E.E.T.E.T.T.T.E.E.T.E.T.E.E.T.T.T.T.T.E.E.T.T.E.T.T.T.E.T.E.E.T.T.T.E.T.T.", -"T.E.T.T.T.T.T.T.T.E.T.T.T.T.T.E.T.T.T.E.T.T.T.E.E.T.E.Y.T.E.T.T.T.T.T.T.T.E.T.T.Y.E.T.T.E.T.T.T.T.T.T.E.T.T.E.T.T.T.T.T.T.T.T.E.T.E.T.T.T.E.T.T.T.T.E.T.T.T.T.T.T.E.T.T.T.E.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.E.T.T.T.T.T.T.E.T.T.T.T.T. l T.E.$ U.T. . i.T.T.T.T.T.T.T.T.T.O 5 T.T.T.T.T.T.T.T.E.T.T.T.B I.E.T.T.E.T.T.T.T.T.T.T.T.T.-. < T.T.T.E.T.T.T.T.T.=. B U.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.E.T.T.E.Y.T.T.E.T.T.T.T.T.T.T.T.T.E.T.T.T.T.T.T.T.E.T.T.E.T.T.T.E.T.T.T.T.E.T.T.T.T.T.T.E.T.T.T.E.T.T.T.T.T.T.T.T.T.T.T.E.T.T.T.T.T.T.T.E.T.T.T.E.T.T.T.T.T.E.T.T.T.E.E.T.T.E.T.T.E.T.", -"T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.E.Y.E.Y.E.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T. l T.T.a @ T.T. . i.T.T.T.T.T.T.T.T.T.O 5 Y.T.T.T.T.T.T.T.T.T.Y.E.i =.T.T.T.T.T.T.T.T.T.T.T.T.T.-. < T.T.T.T.T.T.T.T.T.+. { T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.E.Y.E.Y.Y.E.Y.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.", -"T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.Y.E.Y.E.Y.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T. B T.R.l 5 T.Y. . i.T.T.T.T.T.T.T.T.T.O 5 T.T.T.T.T.T.T.T.T.T.E.Y.+ l T.T.T.T.T.T.T.T.T.T.T.T.Y.-. < T.T.T.T.T.T.T.T.T.=. ; > @ t.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.Y.E.Y.E.E.Y.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.T.E.T.T.T.T.", -"T.T.Y.T.T.T.Y.T.T.T.T.Y.T.Y.T.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T.T.T.T.T.T.T.Y.T.Y.E.Y.E.T.T.T.T.T.Y.T.T.T.T.T.T.T.Y.Y.T.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.Y.T.T.T.T.T.Y.T.T.T.T.Y.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T. B T.T.{ f Y.T.} i.T.T.T.Y.Y.T.T.T.T.O 5 T.T.T.T.T.Y.Y.T.T.T.T.I. ; T.T.T.Y.T.T.T.T.Y.T.T.T.T.-. > T.T.T.Y.Y.T.T.Y.T.+. &.T.T.I.-.s < U.T.T.T.T.T.T.T.T.T.T.T.T.T.Y.Y.T.T.T.T.T.T.T.T.T.Y.T.Y.E.Y.E.T.T.T.T.T.T.T.T.T.T.T.T.T.Y.Y.T.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T.T.T.T.Y.T.T.T.T.T.T.Y.Y.T.T.T.T.T.T.T.T.T.T.Y.Y.T.T.T.T.T.T.T.Y.T.T.Y.Y.T.T.Y.", -"T.Y.T.T.Y.Y.T.Y.Y.T.Y.T.Y.T.T.T.x.T.T.T.Y.T.Y.Y.Y.T.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.Y.T.T.Y.Y.Y.Y.T.Y.Y.T.Y.T.Y.T.Y.Y.T.Y.T.Y.T.T.Y.Y.Y.T.Y.T.Y.Y.Y.T.T.Y.T.T.T.Y.x.T.T.Y.Y.T.T.Y.Y.T.T.Y.Y.T.Y.T.T.Y.Y.T.Y.T.Y.T.Y.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.Y.T.T. l Y.T.*. { Y.Y. . u.T.Y.T.Y.T.T.T.Y.Y.O 1 Y.T.Y.Y.T.Y.T.T.Y.T.Y.,. I.T.x.T.T.Y.Y.Y.T.T.Y.T.Y.-. 4 Y.Y.T.Y.T.T.Y.T.Y.+. &.T.Y.Y.T.T.B &.Y.T.Y.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.T.T.T.Y.Y.T.Y.T.Y.Y.T.T.Y.Y.Y.Y.Y.T.Y.T.Y.Y.Y.T.Y.Y.T.Y.T.Y.T.T.Y.Y.Y.T.Y.T.Y.Y.Y.T.T.Y.T.T.T.Y.x.T.T.Y.Y.T.T.Y.Y.T.Y.Y.Y.T.Y.T.T.Y.Y.T.T.Y.T.Y.T.T.Y.T.T.Y.Y.Y.T.Y.T.Y.T.T.T.T.T.Y.Y.T.Y.Y.T.Y.T.T.Y.T.", -"Y.T.Y.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.T.Y.T.Y.Y.T.Y.Y.T.Y.T.T.x.T.x.T.T.Y.Y.T.Y.Y.T.Y.T.Y.Y.T.Y.Y.T.Y.T.T.Y.Y.T.Y.Y.T.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.T.Y.Y.Y.T.T.Y. k Y.Y.i. +.Y.T.} i.Y.T.Y.Y.Y.Y.T.Y.T.O i Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.} +.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.&. < a a a d a s a a a s a a a a x Y.T.Y.Y.Y.Y.T.Y.Y.+. &.T.Y.T.Y.Y.I.O 4 Y.Y.Y.Y.T.Y.T.Y.Y.T.Y.Y.T.Y.Y.Y.T.Y.Y.Y.Y.Y.T.Y.Y.T.Y.Y.T.Y.Y.Y.Y.Y.T.T.x.T.x.T.T.Y.Y.Y.Y.Y.T.Y.T.Y.Y.Y.T.Y.Y.T.Y.T.Y.Y.Y.Y.T.x.x.T.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.T.Y.T.Y.Y.Y.Y.T.Y.Y.T.Y.T.Y.Y.T.Y.Y.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.", -"Y.Y.T.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.Y.T.Y.Y.T.T.Y.Y.T.Y.Y.T.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.T.Y.Y.Y.Y.T.Y.Y.Y.Y.x.T.x.T.Y.Y.Y.T.x.T.x.x.T.Y.Y.Y.Y.x.T.T.Y.Y.T.Y.Y.Y.Y.Y.T.T.Y.Y.T.Y.Y.Y.Y.T.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.T. B Y.Y.Y. t.Y.Y.} i.Y.Y.Y.T.Y.Y.Y.Y.Y.O 4 Y.Y.Y.Y.T.Y.Y.T.Y.Y.Y.N B Y.Y.Y.Y.Y.Y.Y.Y.T.T.Y.T.&. X.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.T.T.Y.Y.Y.T.Y.T.Y.Y.T.=. &.Y.Y.Y.Y.Y.Y.i I.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.T.Y.Y.T.Y.T.Y.Y.Y.Y.Y.Y.Y.T.T.Y.x.T.T.Y.Y.Y.Y.Y.Y.T.T.Y.x.T.x.T.T.Y.Y.T.Y.x.T.x.Y.Y.T.T.Y.T.T.T.Y.E.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.", -"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.Y.T.Y.x.Y.Y.Y.Y.x.T.x.T.Y.Y.T.Y.Y.Y.x.T.Y.Y.Y.Y.Y.Y.T.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y. k Y.Y.Y.: g.T.Y... u.Y.Y.Y.Y.Y.Y.Y.Y.Y.O 4 Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.4 > x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.&. X.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.Y.Y.x.+. &.Y.Y.Y.Y.Y.Y.B t.Y.Y.Y.x.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.T.x.Y.Y.Y.Y.T.x.T.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.Y.T.Y.Y.Y.Y.Y.Y.x.T.T.x.Y.Y.T.x.Y.Y.Y.T.Y.Y.x.Y.Y.Y.T.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.", -"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.x.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.x.T.Y.Y.Y.Y.T.x.Y.Y.Y.Y.x.Y.Y.Y.T.x.Y.Y.T.x.Y.Y.x.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y. k Y.Y.Y.a O Y.Y.Y.} i.Y.Y.Y.Y.Y.z.Y.Y.Y.O 5 Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.+ I.Y.Y.Y.Y.Y.Y.Y.Y.x.T.Y.*. X.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.Y.x.x.=. &.Y.Y.x.Y.Y.Y.} | Y.Y.x.T.x.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.T.Y.Y.Y.Y.x.T.x.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.x.T.Y.x.Y.Y.T.x.x.T.x.Y.x.T.x.Y.Y.Y.Y.Y.T.x.T.x.x.T.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.", -"Y.Y.Y.Y.Y.Y.x.Y.Y.x.x.Y.Y.Y.z.Y.Y.x.Y.Y.x.Y.x.Y.Y.Y.Y.Y.x.Y.Y.x.Y.x.Y.Y.x.Y.Y.x.x.Y.x.Y.Y.Y.Y.x.x.Y.x.Y.x.Y.Y.Y.Y.x.Y.Y.x.Y.x.Y.x.x.Y.Y.T.x.x.T.x.Y.Y.x.T.x.x.x.Y.x.Y.Y.Y.Y.x.Y.Y.Y.Y.x.Y.Y.x.Y.z.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.x.z.Y.Y.Y.Y.Y.x. k Y.Y.x.l > Y.Y.Y.} u.Y.Y.Y.Y.Y.Y.Y.Y.Y.O 4 Y.Y.x.Y.Y.x.x.Y.x.Y.l. @.Y.Y.Y.Y.x.Y.Y.x.Y.Y.x.&. X.Y.x.Y.Y.Y.Y.Y.Y.x.Y.Y.z.Y.Y.x.x.T.x.Y.Y.x.Y.Y.x.&. +.Y.x.Y.Y.Y.Y.+. { x.x.Y.Y.T.Y.x.Y.x.Y.Y.Y.x.Y.Y.x.Y.x.Y.Y.x.Y.Y.Y.x.Y.x.Y.x.x.Y.x.Y.x.T.x.Y.x.Y.Y.Y.Y.x.Y.Y.x.T.T.x.Y.Y.Y.x.T.x.x.x.Y.Y.x.Y.Y.x.T.x.Y.Y.Y.x.Y.Y.x.x.Y.Y.Y.x.Y.x.Y.Y.Y.Y.Y.Y.Y.z.Y.Y.x.Y.Y.Y.Y.x.Y.x.Y.Y.Y.x.Y.Y.x.Y.Y.Y.Y.x.Y.Y.x.Y.", -"z.Y.z.Y.Y.z.Y.x.x.Y.x.Y.Y.Y.z.Y.x.Y.x.x.x.Y.x.x.Y.x.x.Y.x.x.x.Y.Y.x.x.x.x.x.x.Y.x.Y.x.x.Y.x.Y.x.x.T.Y.x.Y.x.x.x.Y.x.x.x.x.x.x.T.x.Y.x.x.x.x.Y.x.x.x.x.Y.x.x.x.T.Y.Y.x.x.x.x.Y.x.Y.x.x.Y.x.x.x.Y.Y.Y.z.Y.Y.Y.Y.z.z.Y.x.Y.Y.Y.z.Y.x.Y.Y. l Y.x.Y.} s x.x.Y.} u.z.Y.z.Y.Y.z.Y.z.Y.O i x.x.x.x.x.Y.x.Y.x.x.,. l x.Y.Y.Y.x.x.x.Y.x.x.x.&. X.x.Y.x.x.x.x.x.x.Y.Y.z.Y.Y.x.Y.x.x.Y.x.Y.x.x.x.Y.| &.Y.x.x.Y.x.x.*. x x.Y.x.x.x.x.Y.x.Y.x.x.x.Y.x.x.Y.x.x.x.x.Y.x.x.x.x.x.Y.x.Y.Y.x.x.x.x.T.x.x.Y.x.x.x.Y.x.x.x.x.x.x.x.x.x.Y.x.x.x.x.T.x.x.Y.x.x.Y.x.x.Y.x.Y.x.x.Y.x.Y.Y.Y.Y.x.x.Y.x.x.z.Y.z.Y.Y.Y.z.Y.Y.x.x.x.x.Y.x.Y.x.Y.x.Y.x.x.Y.x.x.x.x.Y.Y.Y.x.x.", -"Y.Y.z.Y.x.Y.x.Y.Y.x.z.Y.Y.Y.Y.Y.Y.x.x.Y.Y.x.x.Y.x.Y.x.x.Y.x.Y.x.x.Y.x.Y.Y.x.Y.x.Y.x.x.Y.Y.x.x.x.x.x.x.T.x.x.x.Y.x.Y.x.Y.Y.x.Y.x.Y.x.x.Y.x.Y.Y.x.Y.x.x.Y.x.Y.x.x.x.Y.x.Y.x.Y.Y.x.Y.x.x.Y.x.Y.Y.x.Y.z.z.Y.Y.z.Y.z.z.Y.Y.z.Y.z.Y.z.Y.x.Y. l x.Y.x.*. B x.Y.Y.} y.Y.Y.z.Y.z.Y.Y.Y.Y.. i Y.Y.Y.x.Y.x.Y.x.x.Y.} ; < Y.Y.x.Y.Y.x.Y.x.x.x.Y.@. X.Y.x.x.x.Y.Y.x.x.Y.Y.Y.x.Y.Y.x.Y.x.x.Y.x.Y.x.Y.x.+. @.x.x.Y.Y.x.Y.t. l Y.Y.x.Y.x.x.Y.x.x.Y.x.Y.x.x.Y.x.Y.Y.x.Y.x.Y.x.x.T.x.Y.Y.x.x.Y.Y.x.x.x.x.T.x.x.Y.x.x.Y.x.Y.x.x.T.x.x.x.x.x.T.x.x.Y.x.Y.x.x.Y.x.x.x.Y.x.x.Y.x.x.x.x.x.x.x.x.Y.x.x.x.Y.z.Y.z.z.Y.Y.z.Y.x.Y.x.x.Y.x.x.Y.x.Y.x.x.Y.x.Y.x.Y.Y.x.x.Y.Y.x.", -"z.Y.Y.z.x.x.x.x.x.x.Y.x.z.z.Y.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.z.Y.Y.z.Y.Y.z.Y.Y.z.Y.Y.z.Y.Y.z.x.x.x. l x.x.x.u. } x.x.Y.} y.z.Y.Y.z.Y.z.z.Y.x.O 4 x.x.x.x.x.x.x.x.Y.x.l g O g.x.x.x.x.x.x.x.x.x.x.&. | x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.&. @.x.x.x.x.x.z.y. g Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.x.x.Y.x.Y.x.x.x.x.x.x.z.Y.Y.z.Y.Y.z.Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.", -"x.x.x.x.x.x.x.x.z.x.z.Y.z.z.z.Y.x.x.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.Y.z.z.z.z.Y.Y.z.z.Y.z.Y.z.Y.Y.x.x.x. k Y.x.x.x.. *.x.x.x.} y.x.x.x.x.x.x.x.x.x.O 5 x.x.x.x.z.x.x.x.x.x.4 x i @.x.x.x.x.x.x.x.x.x.z.&. X.x.x.x.x.x.x.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.+. @.x.x.x.x.z.x.y. f x.x.x.x.x.x.x.x.x.x.Y.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.Y.Y.z.z.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.", -"x.x.k.x.z.z.x.z.x.z.Y.z.z.Y.z.z.x.x.x.z.z.x.x.z.z.x.z.z.x.x.k.x.x.z.x.z.z.x.z.x.x.x.z.x.x.z.x.z.x.z.z.x.z.x.z.x.x.z.x.z.z.x.z.x.x.z.x.z.z.x.x.z.z.x.z.x.x.z.x.z.z.x.z.x.z.x.x.k.z.x.x.z.x.z.z.x.z.z.Y.z.Y.z.z.z.z.Y.z.z.z.z.z.z.z.x.x. k z.z.x.z.; u.x.x.x.} y.z.x.z.x.x.z.x.z.z.O 1 z.z.x.z.x.x.z.x.x.Y.O X.l l x.x.z.z.x.x.z.z.x.z.@. | x.x.x.x.z.x.x.x.z.x.z.x.z.x.z.z.x.z.x.z.z.x.z.z.+. @.x.x.z.x.x.x.u. g x.z.x.z.x.x.z.x.z.x.k.x.z.z.x.z.x.z.x.z.x.z.x.z.z.z.x.z.x.z.x.x.z.x.z.z.x.z.z.z.x.x.z.z.x.z.x.z.x.x.x.x.z.z.x.z.x.z.x.z.x.x.z.x.z.x.z.x.z.k.x.x.x.z.x.x.z.x.z.x.z.z.z.z.Y.x.x.k.x.x.z.x.z.x.z.z.x.z.x.z.x.x.z.x.z.x.z.x.z.z.x.x.z.", -"x.z.x.z.x.x.x.x.z.z.Y.z.k.Y.Y.k.x.z.z.x.x.x.x.x.x.z.x.x.x.k.z.x.z.x.x.x.x.z.z.z.z.z.x.x.z.x.x.z.x.x.z.z.x.x.x.x.z.x.x.x.x.z.x.z.x.x.x.x.x.z.z.x.x.z.x.z.z.x.x.x.x.x.x.x.z.x.x.x.x.z.x.z.x.x.x.x.z.Y.z.z.Y.z.z.Y.z.Y.Y.z.z.Y.Y.z.x.z.x. k x.x.z.x.a l.x.z.z.} y.x.z.x.z.z.x.x.x.z.O 1 x.x.z.x.z.x.x.x.x.g. *.| < x.x.x.x.z.x.x.z.x.z.@. | x.x.z.z.x.x.z.z.z.z.x.x.z.x.x.z.z.x.x.x.x.z.x.x.o. @.z.z.x.z.z.z.y. s x.z.x.x.z.z.x.z.x.k.x.x.x.x.z.z.x.x.z.x.z.x.x.z.z.x.x.x.x.z.x.z.x.x.x.z.z.x.z.x.x.z.x.z.x.x.z.x.z.z.x.z.x.x.x.x.x.z.x.z.z.z.x.z.x.z.x.z.x.x.x.k.x.x.z.x.z.x.x.z.x.k.Y.z.z.x.x.z.x.x.x.z.x.x.x.z.x.x.x.x.z.z.x.z.x.x.x.x.x.x.z.z.x.", -"x.k.x.z.z.z.z.z.z.x.z.z.Y.k.Y.z.z.x.z.z.z.z.z.z.z.z.x.k.x.x.x.z.z.z.z.z.x.z.z.z.z.x.z.z.x.z.x.z.z.x.z.z.z.z.z.z.z.z.z.z.x.z.x.z.z.z.z.z.z.x.z.z.z.z.z.z.z.z.z.z.z.z.k.x.z.x.x.k.x.z.z.z.z.z.k.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.x.x.z.x. k z.z.z.z.x ; z.x.z.x.} y.x.z.x.z.z.z.z.z.x.O 4 z.x.z.z.z.z.z.z.z.#. u.t. l.x.k.x.z.z.x.z.z.z.@. | z.z.x.z.z.z.x.z.z.x.z.x.z.z.z.z.z.z.z.z.x.z.z.z.+. @.x.z.z.z.z.z.u. s x.x.z.z.z.x.z.z.x.k.x.x.k.x.z.x.z.x.z.x.z.z.z.z.z.z.z.z.z.z.x.z.z.z.z.z.z.z.x.z.z.z.z.x.z.z.x.z.z.x.z.z.x.z.z.z.z.x.z.z.z.z.x.z.x.x.z.z.x.k.x.k.x.x.z.z.z.z.z.z.x.Y.k.Y.z.k.x.z.x.z.z.z.z.z.z.x.z.z.z.z.x.z.z.z.z.z.z.z.z.k.x.z.z.", -"x.x.z.z.z.z.z.z.z.x.k.x.k.z.z.z.z.z.z.z.z.z.z.z.z.z.x.k.x.k.x.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.x.z.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z. g z.z.z.z.} i x.z.z.z.} y.k.z.z.x.z.z.z.z.z.O 4 z.z.z.z.z.z.z.z.x.( l.l. @.k.z.z.x.z.z.z.z.z.@. | z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.| @.z.z.z.z.z.z.u. a z.z.z.z.z.z.z.z.z.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.x.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.x.x.z.z.z.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.x.x.z.z.", -"k.z.z.k.z.z.z.z.k.k.x.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.k.x.x.k.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.k.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.x.k.z.k.z.z.z.z.z.x.k.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.k.z.z. l z.z.z.x.#. g x.z.z.z.} e.z.z.z.k.z.z.z.z.z.O 1 z.z.z.z.z.z.z.z.x.g @ z.z.; x z.z.z.k.z.z.z.z.z.@. | z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.o. @.k.z.z.k.z.z.e. i z.z.z.z.z.z.z.z.z.k.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.k.x.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.k.k.x.x.k.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.k.z.z.", -"z.z.z.z.z.z.z.z.x.k.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.x.k.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.x.k.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z. k z.z.z.z.f. ( z.z.k.z.} y.z.z.z.z.z.z.z.z.z.O 1 z.z.z.z.k.z.z.z.z.1 < z.z.a 1 z.z.z.z.z.k.z.z.z.@. | z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.| o.z.z.z.z.z.z.y. i x.z.z.z.z.k.z.z.z.z.z.z.z.z.z.k.x.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.x.k.k.k.x.k.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.", -"k.z.k.z.z.k.z.z.k.z.k.z.k.z.k.z.k.z.k.z.k.z.z.z.k.k.x.k.z.k.z.k.k.z.k.z.z.k.z.z.k.z.k.z.k.z.k.z.k.z.k.z.z.k.z.k.z.k.z.k.z.k.z.z.z.z.z.k.z.k.z.k.z.k.z.z.k.z.z.k.z.k.k.z.k.z.z.k.k.z.z.k.z.k.k.z.k.z.k.z.z.k.z.k.k.z.k.k.k.z.k.z.k.z.z. k z.z.k.z.z. | k.z.z.k.} y.k.z.k.z.k.z.k.z.k.O i z.k.z.k.z.z.z.k.z.O s z.k.x l.z.k.z.z.z.k.k.j.@. | z.z.k.k.z.k.z.z.k.k.z.k.z.k.z.z.k.k.k.z.k.z.z.z.o. @.k.k.z.z.k.z.y. i z.k.z.k.z.k.z.k.z.z.k.z.k.z.k.z.k.k.z.z.k.z.k.z.z.k.z.z.k.z.k.z.k.z.z.k.z.k.z.z.k.z.z.z.k.k.z.k.z.k.z.k.z.k.z.k.k.k.z.k.z.z.k.k.z.k.z.z.k.z.z.k.z.k.z.z.k.z.k.z.k.z.k.z.k.k.z.k.x.z.k.x.k.z.k.z.k.z.k.z.k.k.z.z.k.z.k.z.k.z.k.z.k.", -"z.k.z.k.z.k.k.z.k.z.k.z.k.k.k.x.k.k.z.k.k.k.z.k.z.k.z.k.z.k.k.z.z.k.z.k.k.z.k.z.z.k.k.z.k.z.z.k.k.z.z.k.z.k.z.k.x.k.k.z.k.z.k.z.k.z.k.k.z.z.k.z.k.z.k.z.k.z.k.k.z.k.z.k.k.z.z.k.k.x.k.k.z.k.k.z.z.k.z.k.k.z.k.x.z.k.k.z.k.z.k.z.k.z.k. g z.k.k.k.z.> t.k.k.k.z.} e.k.z.z.k.k.z.k.z.k.O 1 k.z.k.z.k.k.z.k.f. x z.z.@. #.z.k.k.z.k.z.k.z.@. | k.z.k.z.k.k.z.k.z.k.z.k.z.k.k.x.k.z.k.z.k.z.k.z.o. @.z.k.z.z.k.k.y. 1 z.z.k.z.k.z.k.z.k.z.k.k.z.k.z.k.x.z.k.k.z.k.z.k.k.k.z.k.z.k.k.k.z.k.k.z.k.z.k.z.k.z.k.z.k.z.k.z.k.z.k.z.k.z.k.z.z.k.k.z.z.k.z.k.k.z.k.z.k.z.k.x.k.k.z.k.k.z.k.k.x.k.z.k.z.z.k.k.z.k.z.k.z.k.z.k.z.k.z.k.z.z.k.k.z.k.z.k.z.k.z.z.k.", -"k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.z.k.k.k.k.k.k.k.z.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k. l k.z.k.k.k.s g.k.k.k.k.) y.k.k.k.k.k.k.k.k.k.O 1 k.k.k.k.k.k.k.k.@. o.k.k.r. x z.k.k.k.k.k.k.k.O. | k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.o. O.k.k.k.k.k.k.e. 1 z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.", -"k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.z.k. l k.k.k.k.k.x + k.k.k.k.k._ e.k.k.k.k.k.k.k.k.k.O 5 k.k.k.k.k.z.z.k.( 8.z.k.k.@ 4 k.z.k.k.k.k.k.k.@. | k.k.k.k.k.k.z.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.o. @.j.k.k.k.k.k.e. 1 k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.z.k.k.k.z.k.k.k.k.k.z.k.k.k.k.k.z.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.z.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.", -"k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k. l k.k.k.k.k.} , k.k.k.k.k.} e.k.k.k.k.k.k.k.k.k.O 1 k.k.k.k.k.k.k.k.g g.k.k.k.a h.k.k.k.k.k.k.k.O. | k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.o. O.k.k.k.k.k.k.y. 1 k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.", -"k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.j.k.k.k.k.k.k.k.k.j.k.k.k.k.j.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.j.k.k.j.k.j.k.k.k.k.k.k.k.k.k.k.k. h k.k.k.j.k.#. s k.k.k.k.k.} e.k.k.k.k.k.k.k.k.k.O 1 k.k.k.k.k.k.k.k.1 @ j.j.k.k.x #.k.k.k.j.k.k.k.O. | k.k.k.k.k.z.k.k.j.k.k.k.k.k.k.k.j.k.k.k.k.k.j.k.` O.k.k.k.k.k.k.e. i k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.j.k.k.k.k.k.k.k.j.k.k.j.k.j.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.k.k.j.k.k.k.k.k.k.k.k.k.j.k.j.k.k.k.j.k.k.j.k.k.k.k.j.k.k.k.k.k.k.j.k.k.k.k.k.", -"j.j.k.j.k.j.j.k.j.k.j.k.j.k.j.j.j.j.k.k.k.j.j.j.k.j.j.k.j.k.j.k.j.j.k.k.k.j.j.j.k.k.j.k.k.j.k.j.j.k.j.j.j.k.k.j.j.k.k.j.j.j.j.k.k.j.k.j.j.j.k.j.k.k.j.j.j.k.j.k.k.k.j.k.j.k.j.k.j.k.j.k.j.k.j.k.j.k.k.j.k.j.j.k.k.j.j.j.j.k.j.j.k.j.k. k j.j.k.k.j.f. x j.j.j.j.j._ e.j.j.k.k.k.j.k.j.j.O 1 j.k.j.k.k.j.j.k.. 4 k.j.j.j.#. x k.k.k.j.j.k.j.@. s ( ( ( ( _ ( ( ( } ( ( ( _ ( ( ( } 8.k.j.k.j.k.j.o. O.k.j.k.j.k.j.e. 1 k.j.j.j.k.k.k.j.k.j.k.k.j.k.j.k.j.j.j.k.k.k.k.j.j.j.k.j.k.j.k.j.j.j.k.j.j.j.k.k.j.j.k.j.k.j.j.j.k.j.j.k.j.j.k.k.k.j.j.j.j.j.k.k.j.k.k.j.j.j.k.j.k.j.j.k.j.j.k.j.k.k.j.j.j.k.k.j.k.k.k.j.k.k.j.k.j.k.j.k.j.j.k.j.k.j.k.j.k.k.j.j.j.", -"j.k.j.k.k.j.j.k.j.k.k.j.k.j.k.j.j.k.j.j.j.k.k.j.j.k.k.j.j.k.k.j.j.k.j.j.j.k.k.j.k.j.j.k.j.j.j.j.j.k.j.k.j.j.j.j.k.j.j.k.k.j.j.j.j.j.k.k.k.j.j.k.j.j.k.j.j.k.j.k.k.j.j.j.j.j.j.k.j.k.j.j.j.j.k.j.k.j.j.k.j.k.k.j.j.k.k.j.k.j.j.j.j.k.j. h j.j.j.j.j.k.. | k.k.j.k.j.} e.j.k.j.j.j.j.j.k.j.O 1 k.j.j.k.j.j.k.r. g j.k.j.k.f. i j.j.j.k.j.k.j.@. ( j.k.k.j.k.j.o. o.j.j.k.k.j.k.e. 1 j.j.k.j.k.k.j.k.j.k.j.j.k.j.j.k.j.j.k.k.j.j.k.k.j.j.k.k.j.k.j.j.j.j.j.j.k.k.j.j.j.k.j.j.k.j.k.k.j.k.j.j.k.k.k.j.j.k.j.j.k.k.j.j.k.j.j.j.j.j.k.j.j.k.j.k.k.j.k.j.j.j.j.k.j.j.j.j.j.j.k.k.j.j.k.k.j.j.j.k.j.j.j.k.j.j.k.k.j.j.k.k.j.", -"k.j.k.j.j.j.k.j.j.k.j.j.k.j.j.k.j.j.k.j.k.j.j.k.j.k.j.j.k.j.j.j.j.j.k.j.k.j.j.k.j.j.k.j.j.k.j.j.k.j.k.j.k.k.j.k.j.j.k.j.k.j.k.j.j.k.j.j.j.k.k.j.j.k.j.k.j.j.k.j.j.j.k.k.j.k.j.k.k.j.j.k.k.j.j.k.j.k.j.j.j.k.j.j.k.j.k.j.j.j.k.k.j.j.k. k j.j.k.k.j.j.< #.j.j.k.j.j._ e.k.j.k.j.k.k.j.j.j.O 1 j.k.j.j.j.k.k.O. ( k.j.k.j.j.@ j.k.j.k.j.j.j.O. x k.j.j.k.j.k.` O.j.k.j.j.j.k.y. 1 k.k.j.j.k.j.j.k.j.j.k.j.j.j.k.j.k.k.j.j.k.j.j.j.k.j.k.j.j.k.j.j.j.j.k.k.j.j.k.j.k.j.k.j.j.k.j.j.j.j.k.k.j.j.j.k.j.j.k.j.k.j.j.k.j.k.j.k.k.j.j.k.j.j.k.j.j.k.j.j.k.k.k.j.k.k.j.k.k.j.j.k.j.k.j.j.j.k.j.j.k.k.j.j.k.k.j.j.j.k.j.j.k.", -"j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j. g j.j.j.j.j.d.s r.j.j.j.j.j._ e.j.j.j.j.j.j.j.j.j.O 1 k.j.j.j.j.j.j.( o.j.j.j.j.j.a 8.h.j.j.j.j.j.O. ( j.j.j.j.j.d.o. O.k.j.j.j.j.j.e. 1 j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.", -"j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j. l j.j.j.j.j.j.x h.j.j.j.j.j.} 0.j.j.j.j.j.j.j.j.j.O 1 j.j.j.j.j.j.j.g 0.j.j.j.j.d.( ( k.j.j.j.j.j.O. x j.j.j.j.j.j.` O.j.j.j.j.j.j.e. 1 j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.", -"j.d.j.d.d.j.d.j.d.j.j.j.j.d.j.j.j.j.j.d.j.d.j.j.j.d.j.j.j.j.d.j.j.j.j.j.j.d.j.d.d.j.j.j.j.j.d.j.j.j.j.j.j.j.d.j.j.d.j.j.d.j.j.j.j.j.d.j.j.j.j.d.j.j.j.j.j.d.j.d.j.d.j.d.d.d.j.d.j.j.j.d.j.d.j.j.j.j.j.j.j.d.j.j.j.d.j.j.j.d.j.j.j.j.j. h j.j.j.j.d.d.| ; d.j.j.d.j.d._ e.j.d.j.d.d.j.d.j.d.O 1 j.j.d.j.j.j.j., h.j.j.d.j.j.8. 1 j.j.d.j.j.j.O. z d.j.j.j.d.d.o. O.j.j.d.j.j.j.9. i j.j.d.j.d.j.j.d.j.d.j.j.j.d.j.j.j.d.j.j.j.d.j.j.j.j.d.j.j.j.j.d.j.j.j.j.j.j.j.j.d.j.d.j.d.d.j.d.j.j.d.d.j.j.j.d.j.j.j.j.j.j.j.j.d.d.j.d.j.j.j.j.j.j.j.j.d.j.j.j.d.j.j.j.j.j.d.j.d.d.j.j.j.j.d.j.j.d.j.j.j.j.d.j.j.j.j.j.j.j.j.j.d.", -"j.j.j.j.j.j.j.j.j.j.j.d.j.j.d.j.d.d.j.j.j.j.d.j.j.j.j.d.d.j.j.j.d.d.j.j.j.d.j.j.j.j.d.j.d.j.j.j.d.d.j.j.d.j.j.j.j.j.j.d.j.j.d.j.j.d.j.j.d.j.j.j.j.j.j.d.j.j.j.j.j.d.j.j.j.j.j.j.d.j.j.d.j.j.d.j.j.d.j.d.j.j.j.d.j.j.d.j.j.j.j.d.j.j.j. l d.d.j.j.j.d.8. i j.j.d.j.j.j._ e.j.j.j.j.j.j.j.j.j.O 1 d.j.j.j.d.j.j.. ; d.d.j.j.j.d.h.. h.j.j.d.j.j.O. x j.j.d.j.j.d.o. O.j.j.j.d.d.j.e. 1 j.j.j.j.j.d.j.j.j.j.j.j.d.j.j.d.j.j.j.d.j.j.j.d.j.j.j.j.d.d.j.j.j.d.j.j.j.d.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.d.j.j.j.j.j.d.j.d.d.j.j.j.j.j.j.j.d.d.j.d.j.j.j.d.j.j.j.j.d.d.j.j.j.j.j.j.j.d.j.j.j.j.d.j.j.j.d.j.j.d.j.j.j.d.j.d.d.j.j.", -"d.d.d.j.d.j.j.d.d.j.j.d.j.d.j.d.j.d.d.j.d.j.j.d.d.j.j.d.j.d.j.d.j.d.d.j.d.j.d.j.d.j.j.j.d.j.d.j.j.d.j.j.d.j.d.j.d.j.d.j.d.j.j.d.d.d.j.d.d.j.d.d.d.j.j.d.d.j.d.j.j.d.j.j.d.j.d.j.j.j.d.j.j.d.j.j.j.d.d.j.d.j.j.d.d.j.d.d.j.d.d.j.j.j.d. h d.j.d.j.d.d.f. g j.j.j.d.j.j._ 0.d.d.d.j.d.j.j.d.d.O 1 d.j.d.j.j.d.r. i j.j.j.d.d.j.d.1 8.d.j.d.d.d.O. x d.d.d.d.j.d.` O.d.d.j.j.j.s.e. 1 d.d.d.d.j.d.j.j.d.d.j.j.d.j.d.j.d.d.j.j.j.d.j.j.d.d.j.j.d.j.d.j.d.j.d.j.d.j.d.d.j.d.d.d.j.d.j.j.d.d.d.j.d.d.j.d.d.d.j.j.j.j.j.d.j.j.j.d.d.d.j.j.d.j.j.d.j.d.j.d.d.j.j.d.j.d.j.d.j.d.j.d.d.j.j.d.j.d.j.d.j.j.d.j.j.j.d.d.j.j.j.d.j.", -"d.j.j.d.d.d.d.j.d.d.d.j.d.d.d.d.j.d.j.d.d.d.d.d.d.d.d.j.j.d.d.j.j.d.j.d.d.d.j.d.d.d.d.d.d.d.d.j.j.d.d.d.d.d.d.j.d.d.j.d.d.d.d.j.d.j.j.d.j.d.d.j.d.d.d.j.d.d.d.d.d.j.d.d.j.d.d.j.d.d.d.d.d.j.d.d.d.j.d.d.d.d.d.d.d.j.d.j.d.j.d.d.d.d.j. h d.j.d.d.j.j.d.. ( d.d.d.d.d.d._ 0.d.j.j.d.d.d.d.j.d.O 1 d.d.d.d.d.j.O. j d.d.d.d.j.j.d.x ( d.d.d.j.d.O. ( d.d.d.d.j.d.o. O.j.d.d.s.j.s.e. 1 d.j.d.j.d.d.d.d.j.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.j.j.d.d.j.d.d.d.d.d.j.j.d.j.d.j.d.d.d.d.j.d.j.j.d.j.d.d.j.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.j.d.d.d.d.d.j.d.j.d.d.d.d.d.d.d.d.j.d.d.j.d.d.d.j.d.d.d.d.d.j.d.d.d.d.j.d.d.d.d.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.j.d.d.d.d. g d.d.d.d.d.d.d., O.d.d.d.d.d.d._ 0.d.d.d.d.d.d.d.d.d.O 1 d.d.d.d.d.d.( _ d.d.d.d.d.d.d.O. i d.d.d.d.d.O. x d.d.d.d.d.d.' ] d.d.d.d.d.s.e. 1 d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d. l d.d.d.d.d.d.d.p 9.d.d.d.d.d.d._ 0.d.d.d.d.d.d.d.d.d.O 1 d.d.d.d.d.d.p #.d.d.d.d.d.d.d.q. . d.d.d.d.d.O. x d.d.d.d.d.d.` O.d.d.d.d.d.d.9. 1 d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.j.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.s.s.d.s.d.d.d.s.d.d.d.d.d.s.j.j.s.d.d.d.d.d.s.s.j.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.d.d.d.s.d.s.d.d.d.d.d.d.d.d.d. l s.j.s.s.d.d.d.z p.j.s.d.d.d.d._ 9.d.d.s.d.d.d.d.d.d.O 1 s.d.d.d.d.s., q.d.d.d.d.d.d.d.d.; 8.j.d.d.d.O. x j.d.d.s.d.s.` ] d.d.d.s.d.j.9. i d.s.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.s.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.s.d.d.s.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.", -"s.d.s.d.d.s.d.s.d.s.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.s.d.d.s.s.s.d.s.d.s.d.s.j.s.s.d.d.s.d.s.d.s.d.s.d.s.d.d.s.d.d.d.s.d.s.d.d.s.d.d.d.d.s.s.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.s.d.s.d.d.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.s.d.s.d.d.s.d.. h j.d.s.d.d.d.s.` + d.d.d.d.d.s.d.) 9.s.d.d.d.d.s.d.d.s.O i d.d.s.d.s.s.. . d.d.d.d.d.s.s.d.s.h ( d.d.s.s.O. ( d.d.d.d.d.d.' O.s.s.d.s.d.s.9. 1 d.d.d.d.d.s.d.s.d.s.d.s.d.s.d.s.d.s.d.s.d.s.s.d.d.d.s.d.s.s.d.s.d.s.d.s.d.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.d.s.d.s.s.d.s.d.d.s.d.d.s.d.s.d.d.d.d.s.s.d.d.d.d.s.d.s.s.d.s.d.d.d.d.d.d.d.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.s.d.d.d.", -"d.s.s.s.s.s.s.d.s.s.s.d.s.s.s.s.s.d.s.d.s.d.s.d.s.d.s.d.s.s.d.s.s.j.s.d.s.s.s.d.s.j.s.d.s.s.s.d.s.d.d.s.d.s.s.s.s.s.s.s.s.s.s.d.d.s.d.s.d.s.s.s.s.s.d.s.s.s.s.s.s.d.d.s.s.s.s.s.s.d.d.s.s.d.s.s.s.d.s.d.s.d.s.s.d.s.d.s.s.s.d.s.s.d.d. g s.s.s.s.d.s.s.8. , d.s.s.d.s.s.s.) 9.s.d.s.d.s.s.d.s.s.O 1 s.d.d.s.s.9. , s.d.s.s.s.d.s.s.s.O. i s.s.d.d.] z s.s.s.d.s.s.' ] s.d.s.s.d.s.0. 1 s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.d.s.s.d.d.s.d.s.s.s.s.s.s.d.d.s.d.s.s.d.d.s.s.s.d.s.s.s.d.s.s.d.d.s.d.s.s.d.d.s.s.d.s.s.d.d.s.d.s.s.s.s.s.s.d.d.s.s.s.s.s.d.s.d.s.d.s.d.s.d.d.s.s.d.d.s.s.d.s.s.d.s.s.s.s.s.s.d.d.s.s.s.s.s.s.s.s.s.", -"d.s.d.s.d.s.d.s.s.d.s.d.s.d.d.s.s.s.d.s.d.s.s.s.d.s.s.d.s.d.s.s.s.s.s.s.s.j.s.s.s.s.d.s.s.d.s.d.s.s.s.s.d.s.d.s.d.s.d.s.s.d.s.d.s.s.d.s.s.s.d.d.d.s.s.d.d.d.s.d.s.d.s.s.s.d.d.s.d.s.d.s.d.s.d.d.d.s.d.s.d.s.s.d.s.d.s.d.d.s.s.d.s.s.j. h d.s.d.d.s.d.d.p. p s.d.d.s.s.s.s._ 9.d.s.s.d.s.d.s.s.s.O 1 d.s.s.d.s.' p s.s.s.d.s.d.s.s.s.q. . s.d.s.d.] z s.s.d.s.d.s.' O.s.s.s.d.s.s.0. 1 s.d.s.d.s.s.d.s.s.s.d.s.d.s.s.s.s.d.s.s.s.d.s.d.s.s.d.d.s.s.d.s.s.d.s.s.d.s.d.s.s.s.d.s.d.s.s.s.s.s.s.d.s.s.s.d.s.s.d.s.s.s.s.s.d.d.s.d.s.s.s.s.d.d.d.s.s.s.d.s.s.d.s.d.s.s.d.s.s.s.s.d.s.s.d.s.d.d.d.s.d.s.d.s.s.s.d.d.s.d.d.s.d.", -"s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s. h s.s.s.s.s.s.s.s.O x s.s.s.s.s.s.s.) 9.s.s.s.s.s.s.s.s.s.. 1 s.s.s.s.s.( ( s.s.s.s.s.s.s.s.s.a., 8.s.s.s.] z s.s.s.s.s.s.` ] s.s.s.s.s.a.9. 5 s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.d. g s.s.s.s.s.s.s.s.< ) s.s.s.s.s.s.s._ 9.s.s.s.s.s.s.s.s.s.O 1 s.s.s.s.s.p | s.s.s.s.s.s.s.s.s.p.( ) s.s.s.] z s.s.s.s.s.s.' ] a.s.s.s.s.s.9. 1 s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.a.s.a.s.s.s.s.a.s.a.a.s.s.s.a.s.s.s.s.s.a.s.s.s.s.a.s.s.s.s.a.s.a.s.s.s.s.a.a.s.a.s.s.a.s.s.a.s.s.s.a.s.s.s.s.s.s.a.s.a.s.s.s.s.s.s.a.s.a.a.s.a.a.s.s.s.a.s.s.s.a.s.a.s.s.s.s.s.a.s.s.s.a.a.s.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.s.a.s. h s.a.s.s.s.a.a.s.g <.p.s.s.a.s.a.s.) 9.s.s.s.a.s.a.s.s.a.. 1 s.s.s.s.s., 8.s.s.s.w.s.s.w.s.s.s.<. p s.a.a.] z s.s.a.a.s.s.' ] a.s.s.a.s.s.9. i a.s.s.a.s.s.s.a.s.s.a.s.s.s.s.a.s.s.w.s.s.s.a.s.a.a.s.s.s.s.s.a.s.s.s.s.a.a.s.s.s.s.a.s.s.s.s.a.s.s.s.s.s.a.a.s.s.a.s.s.s.a.s.s.s.s.s.s.a.s.s.s.a.s.s.a.a.s.a.s.s.s.s.s.a.s.a.s.s.a.s.s.s.s.a.s.a.s.a.s.s.s.s.a.a.s.s.s.a.s.s.s.s.", -"a.a.s.s.s.s.a.a.s.s.s.s.s.s.a.a.s.s.s.a.a.s.s.s.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.s.a.s.s.a.s.a.s.s.a.s.s.s.a.s.a.a.s.s.s.s.a.a.s.a.a.s.s.s.s.s.s.s.s.s.a.a.s.s.a.s.s.s.a.s.s.a.a.s.s.a.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.s.a.s.a.s.a.s.s. h s.s.a.a.s.s.s.w.( q.s.s.s.s.s.s.a.) e.a.a.s.s.s.s.a.a.s.O 1 w.s.s.s.s. p.s.s.s.s.s.s.s.s.s.s.p.. O s.a.s.] z a.a.s.s.a.p.' ] s.a.s.a.s.s.9. . . 1 s.a.a.s.s.a.s.s.s.a.s.s.a.a.s.s.s.s.s.s.s.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.s.s.a.a.s.s.s.a.a.s.s.s.a.s.a.s.s.s.s.a.s.s.a.s.s.s.a.s.a.s.s.s.s.a.s.s.a.s.s.s.s.s.s.a.s.a.s.a.s.s.s.a.s.s.a.a.s.s.s.s.s.s.s.a.a.s.s.s.s.a.s.s.a.a.s.s.", -"s.a.a.s.a.a.s.a.s.a.s.s.a.s.a.s.a.a.a.s.a.s.a.s.s.a.s.a.s.a.s.a.a.s.s.a.s.s.s.a.a.s.a.s.a.s.s.s.a.s.s.s.a.s.s.a.a.a.s.s.a.s.s.s.a.s.s.a.s.s.a.s.a.s.s.a.s.s.a.s.a.a.s.s.a.s.s.s.s.a.a.s.a.s.s.a.a.s.a.s.a.s.a.s.a.a.s.a.a.s.a.s.a.s.s.j j j j j j j j j j j j j j j j j j j j j ] a.a.s.s.a.a.a.a.<.j j j j j j j j j j j j j j j w.s.s.s.a.s.s.a.<.j j j j j j j j j j j j j j j j j j j j j q.s.a.s.a.s.s.a.s.s.( h g h h h h h h h h h h h h j h h h h h h h h ) s.s.s.s.q.j j j j j j j j j j j j j j j j j j j j j j j z s.s.a.s.s.s.s.a.s.s.a.s.) j j j j j j j j j j j j j j j j j j j j j j q.s.a.0.h h h h h h h h h h h h h j h h h h h h h h h h h h h h h h j h h h h h h h h h h h [ a.s.a.s.s.a.9.j j j j j j j j j j j j j j j j j j j j j j j j 9.a.a.a.s.a.a.q.j j j j j j j j j j j j j j j j z j j j j j ) s.a.s.s.a.s.a.s.a.a.a.s.s.a.s.s.a.s.w.a.s.a.s.a.s.s.a.s.s.a.a.s.a.s.a.s.a.s.a.s.a.a.s.a.s.a.s.s.a.s.a.a.s.a.s.s.s.a.a.s.a.s.s.a.s.s.a.s.s.a.s.s.a.s.s.a.s.s.a.a.s.a.s.a.s.s.a.s.s.a.s.a.s.s.a.s.a.s.a.s.s.w.s.s.a.a.s.a.s.a.s.a.s.", -"a.a.s.a.a.s.s.a.a.a.a.a.a.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.s.s.w.w.w.s.w.a.a.a.p.a.s.s.s.w.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.w.a.a.s.a.s.s.s.w.w.s.a.w.a.a.a.a.a.s.a.a.a.a.p.a.w.s.a.w.a.a.s.a.a.a.s.a.s.s.a.s.a.a.w.s.a.a.a.a.a.a.a.a.w.s.w.a.a.a.a.s.a.a.w.s.s.w.w.s.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.s.w.w.s.s.a.7.s.w.s.a.w.a.a.a.s.s.w.s.a.a.a.a.a.s.s.s.w.w.s.a.w.w.s.s.w.a.a.a.a.s.a.a.a.a.a.a.a.p.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.s.a.a.a.a.a.a.s.s.a.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.s.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.s.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.w.s.s.s.w.s.s.w.s.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.a.s.s.w.a.a.a.a.a.a.w.w.w.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.w.s.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.w.s.w.a.a.a.a.a.a.a.a.s.w.a.a.w.a.a.a.a.s.w.a.s.w.w.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.s.w.a.a.a.a.a.a.a.a.a.a.a.a.w.s.a.a.a.a.a.a.w.w.s.s.a.a.a.a.s.w.w.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.w.w.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.w.s.a.a.w.w.s.s.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.w.a.w.s.w.a.a.a.a.a.a.s.s.w.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.w.s.w.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.w.a.w.a.a.a.a.w.a.a.a.a.a.a.s.w.a.a.a.a.a.a.a.w.a.a.w.w.s.w.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.w.w.s.w.a.a.a.a.a.a.a.a.a.a.a.a.w.w.a.a.a.a.a.a.w.s.w.w.a.a.a.a.w.s.w.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.w.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.w.s.w.w.a.a.w.s.w.w.a.a.w.a.", -"a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.s.w.w.s.w.a.a.a.w.w.s.w.w.s.w.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.s.s.w.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.w.s.w.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.s.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.s.a.a.a.w.s.w.a.s.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.w.a.a.a.a.a.a.a.a.s.s.w.w.s.w.a.a.w.s.w.s.a.a.a.a.", -"w.a.w.a.w.w.a.w.a.a.a.w.w.a.w.a.a.a.7.a.a.w.w.a.a.a.7.a.w.a.w.a.w.a.w.a.a.a.w.a.w.a.w.a.a.w.w.a.a.w.a.a.a.a.a.w.w.a.a.a.w.a.w.a.a.a.w.a.a.a.a.w.w.a.w.a.a.w.a.w.a.a.w.a.a.w.w.a.w.a.w.w.a.a.w.a.w.a.w.a.a.w.a.w.a.a.a.w.w.a.w.a.a.a.w.a.a.a.7.a.a.a.w.a.w.a.a.w.a.a.w.a.a.w.a.a.w.w.a.w.a.a.w.a.a.w.w.a.a.w.w.a.w.a.a.a.a.w.w.a.w.w.w.s.w.a.w.a.w.s.w.w.w.s.w.w.a.a.a.w.a.w.a.a.a.w.w.a.a.a.7.a.a.w.a.a.w.a.a.w.w.a.w.a.7.a.w.a.a.w.a.a.w.a.a.w.a.a.a.w.a.a.w.a.w.a.w.a.w.a.a.w.a.a.a.w.w.a.w.a.w.a.a.a.w.a.a.w.w.a.a.a.w.a.w.a.w.a.a.w.w.a.a.7.w.a.w.a.w.w.w.a.a.w.w.a.w.w.a.w.a.a.w.a.a.a.w.a.s.w.w.a.a.w.w.a.a.w.a.a.a.w.7.a.w.w.a.w.a.w.w.a.a.w.a.a.w.a.a.w.w.s.w.w.w.a.w.a.a.w.a.w.a.a.a.w.a.a.w.a.a.w.a.w.a.a.a.w.w.a.w.a.a.a.a.w.a.a.7.a.w.a.w.a.w.a.a.w.a.w.w.w.w.a.w.a.a.a.a.a.w.a.a.a.w.a.w.a.w.a.a.w.w.a.w.a.w.w.a.w.a.w.a.a.a.a.a.w.a.a.w.a.a.w.a.a.w.a.w.w.w.a.w.a.w.a.w.w.a.w.a.a.w.a.a.w.a.a.a.w.a.w.w.a.a.w.a.w.w.a.w.w.w.a.w.a.w.w.a.w.w.a.w.a.w.a.a.w.a.w.w.a.7.a.w.a.a.a.w.w.a.w.a.a.w.w.a.a.a.w.w.a.w.a.w.a.w.w.s.w.w.a.a.w.w.w.w.a.w.a.w.w.", -"w.w.w.w.w.a.w.w.w.w.w.a.w.w.a.w.w.a.a.a.a.a.w.a.a.w.w.a.w.a.w.a.w.w.a.w.w.w.w.a.a.w.w.w.w.w.a.w.w.w.w.w.a.w.w.w.a.w.w.w.w.a.w.w.w.a.w.w.w.w.a.w.w.w.w.w.a.w.w.w.w.w.a.w.w.w.a.w.w.w.w.a.w.w.w.a.w.w.a.w.w.w.w.a.w.w.w.a.w.a.w.w.a.a.w.a.a.w.w.w.w.w.a.w.w.w.w.w.w.w.w.a.w.w.w.w.w.a.w.w.w.w.w.w.w.w.a.w.w.w.a.w.w.w.a.w.w.w.w.a.w.w.w.w.a.w.w.w.w.a.w.w.w.s.w.w.a.a.a.a.7.a.a.w.a.w.w.a.a.w.w.a.w.w.w.w.a.w.w.w.a.a.a.a.a.a.a.w.w.w.w.w.a.w.w.w.a.w.a.w.w.w.a.a.w.a.w.a.w.a.w.w.w.w.w.a.w.w.a.w.w.a.a.7.7.a.w.w.a.w.w.w.w.a.w.w.a.w.w.w.a.a.a.a.w.a.w.a.w.a.w.w.w.a.w.w.w.a.a.a.a.a.w.a.a.7.7.a.7.w.w.a.w.w.w.a.w.w.w.w.7.a.a.a.w.a.w.w.w.a.a.w.w.w.w.w.a.w.w.w.w.w.w.a.w.w.w.w.w.a.w.w.w.w.w.w.w.w.a.w.w.w.w.a.w.w.w.a.w.a.w.w.7.a.7.a.a.w.w.w.w.a.a.w.w.w.w.w.w.a.w.a.w.w.w.w.a.w.w.w.a.w.w.w.w.a.a.w.a.w.7.a.w.a.w.w.w.a.w.a.w.w.w.w.a.w.w.w.w.w.a.w.w.w.w.w.w.w.w.a.w.w.w.a.a.w.w.w.w.w.a.w.w.w.w.a.w.a.w.w.w.a.w.a.w.w.w.w.w.w.w.a.w.a.w.w.w.a.w.a.w.w.w.a.a.w.w.w.w.w.a.w.w.w.w.a.w.w.w.a.w.w.a.w.w.a.w.w.w.w.a.w.w.a.w.w.w.w.w.w.a.w.w.w.w.a.a.w.w.w.w.a.", -"w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.7.a.7.7.a.7.w.w.w.w.w.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.7.a.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.7.a.7.w.w.7.w.a.7.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.7.a.7.w.w.w.w.w.w.w.w.w.w.w.w.7.w.w.w.7.a.w.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.a.w.w.w.w.w.w.w.w.w.w.w.7.w.w.w.7.a.7.7.a.7.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.7.a.7.a.7.a.a.w.w.w.w.w.w.w.w.w.w.w.w.a.7.7.a.7.w.w.w.w.a.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.7.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.", -"w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.a.7.a.7.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.w.a.w.w.7.a.7.a.7.a.a.7.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.7.a.7.a.7.a.w.w.w.w.w.w.w.w.w.a.a.7.7.a.a.a.w.w.w.w.w.7.a.7.a.7.a.w.w.w.a.w.w.a.7.a.7.w.w.w.w.a.7.a.7.a.7.w.w.w.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.w.w.a.7.a.a.7.a.7.a.7.w.w.w.w.w.w.w.w.w.w.7.a.a.w.w.w.w.w.w.w.w.w.7.a.7.a.7.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.7.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.a.7.a.a.7.a.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.", -"w.w.w.w.w.w.w.w.w.7.w.w.w.7.w.w.w.w.w.w.w.7.w.w.w.w.7.w.w.w.w.7.w.w.w.w.w.w.w.w.7.w.w.7.w.w.7.w.w.w.w.7.w.w.w.w.w.w.w.7.7.w.w.w.w.w.w.w.7.w.w.w.a.7.a.7.w.7.w.w.7.w.w.7.w.w.7.w.w.w.w.w.w.7.7.w.7.w.w.w.w.w.7.w.w.w.w.w.w.w.7.w.7.w.a.7.7.a.7.a.7.a.w.7.7.w.w.7.w.w.w.7.w.w.w.w.w.w.w.7.7.w.w.w.w.7.w.w.7.w.w.w.7.7.w.w.7.w.w.w.w.w.w.w.7.w.w.w.w.w.w.7.w.w.w.7.w.w.7.a.7.a.7.a.w.7.7.w.a.7.7.w.7.w.7.w.7.a.7.a.7.7.7.a.7.w.w.w.a.7.a.7.w.7.w.w.7.w.w.7.7.a.7.a.w.w.w.7.7.a.7.a.7.a.w.w.w.7.w.7.w.w.w.7.w.w.w.w.w.w.w.7.7.w.w.w.w.7.w.w.w.7.w.w.w.w.w.w.w.7.w.w.w.w.w.w.w.w.w.7.7.a.7.w.w.7.w.7.7.a.7.a.7.a.7.w.w.w.7.w.w.w.w.w.7.w.7.w.a.7.7.w.7.w.a.7.a.7.a.7.w.w.w.7.w.w.7.w.w.w.w.7.7.w.w.w.w.7.w.w.w.w.w.w.w.w.w.w.w.w.w.7.w.7.w.w.w.7.w.w.w.w.w.w.w.7.w.w.w.w.7.w.w.w.7.w.w.w.w.7.w.w.7.w.w.7.w.w.7.w.w.w.w.w.7.w.w.w.7.w.w.w.w.w.w.7.w.w.w.w.w.7.w.w.w.7.w.w.w.w.w.w.7.w.w.w.w.w.7.w.w.w.w.w.7.w.w.w.w.w.w.7.w.w.w.w.w.w.w.w.w.w.7.w.w.w.7.a.7.w.w.7.w.w.w.7.w.w.w.w.7.w.w.w.7.w.w.w.w.w.7.w.w.w.7.w.w.w.w.w.w.w.w.7.w.w.w.w.w.w.w.w.w.w.w.7.w.w.w.w.w.7.", -"7.w.w.w.w.7.7.7.w.7.w.w.w.7.7.w.w.7.7.w.w.w.7.7.7.w.w.7.7.w.7.7.w.w.7.w.w.7.7.7.w.w.7.w.7.w.w.7.w.7.7.w.7.w.7.w.w.7.7.w.7.w.7.w.7.7.w.w.w.7.7.7.7.a.a.7.7.a.7.w.w.w.7.w.7.w.w.7.w.7.w.w.7.w.w.w.w.7.7.w.7.w.7.w.7.7.w.7.7.w.w.w.7.w.7.7.w.7.w.7.7.a.7.a.w.w.7.w.w.7.7.w.7.w.7.7.w.w.7.w.w.w.w.7.7.w.7.w.w.7.w.7.w.7.7.w.w.7.w.7.7.w.w.w.w.w.7.w.w.7.7.w.7.w.w.w.7.w.7.7.w.7.7.a.7.a.a.7.7.w.7.w.7.w.w.7.7.7.7.7.7.w.7.7.7.w.7.7.7.a.7.w.7.a.7.w.w.w.7.w.a.7.7.w.7.w.w.7.7.7.7.7.7.7.w.w.7.w.w.7.w.7.7.w.7.w.7.w.w.7.7.w.7.w.7.w.7.7.w.w.w.7.7.w.w.7.7.w.w.w.7.7.7.w.7.7.7.w.7.w.w.7.w.7.7.a.7.a.7.a.w.7.7.a.a.7.7.w.w.w.7.7.w.7.7.w.w.7.w.w.w.7.w.w.7.a.w.7.7.7.w.7.7.w.7.w.w.w.w.w.7.w.w.w.w.w.7.w.7.w.7.7.w.7.7.7.w.7.7.w.w.w.7.7.w.w.w.7.7.w.w.7.7.w.7.w.7.7.7.w.w.w.w.7.w.7.w.7.w.7.7.w.w.w.7.w.7.7.w.w.w.7.7.w.w.w.w.7.w.7.w.7.w.7.7.w.7.w.w.7.7.w.w.7.7.w.w.7.w.w.7.w.w.7.7.w.w.w.w.w.7.w.7.w.7.w.7.w.7.w.7.w.7.w.w.7.w.7.7.w.7.w.7.w.7.7.w.7.a.7.7.7.w.w.w.w.7.7.7.w.w.7.7.w.7.w.7.w.7.w.w.7.w.7.w.7.w.7.7.7.w.7.7.w.w.w.w.w.w.w.w.7.7.w.w.w.7.7.7.w.w.7.", -"7.7.7.w.7.w.7.7.w.w.7.7.7.w.7.7.7.w.7.7.7.7.7.w.7.7.w.7.w.7.7.7.7.7.7.7.7.7.w.7.7.7.7.w.7.7.w.7.7.w.7.7.7.w.7.7.7.w.7.7.w.7.7.7.7.w.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.7.7.7.7.w.7.w.7.7.7.w.7.w.7.7.w.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.w.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.w.7.7.a.7.7.w.7.7.w.w.7.7.w.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.a.7.7.7.7.w.7.7.7.w.7.7.7.w.7.7.7.w.7.7.7.w.7.7.w.7.7.7.7.w.7.7.7.w.7.7.7.w.7.7.7.7.7.w.7.7.7.w.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.w.7.7.7.w.7.7.7.7.w.7.7.7.7.7.w.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.w.w.7.7.7.7.7.7.7.7.w.7.7.7.w.7.7.7.w.7.7.w.7.7.w.7.7.7.7.7.w.7.7.w.7.7.w.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.w.7.7.7.w.7.7.7.w.7.7.7.w.7.7.w.7.7.w.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.w.7.w.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.w.7.", -"7.w.w.7.7.w.7.7.7.w.7.w.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.w.7.7.w.7.7.w.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.w.7.7.7.7.7.w.w.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.w.7.7.7.w.7.7.w.7.7.w.w.7.7.7.7.w.7.7.7.7.7.7.7.w.7.7.w.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.7.w.7.7.7.7.w.7.w.7.7.7.7.7.7.w.7.7.7.w.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.w.7.7.w.7.w.7.7.w.7.7.7.w.7.7.7.w.7.w.7.7.7.7.7.w.7.7.7.w.7.w.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.w.7.7.w.7.7.w.", -"7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.w.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.w.7.w.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.w.w.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.w.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.", -"7.7.7.7.7.7.7.7.7.7.7.7.7.w.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.", -"7.7.5.7.5.7.7.7.5.7.7.5.7.5.7.7.6.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.6.7.6.7.6.7.6.7.7.7.6.7.7.7.6.7.7.6.7.7.7.6.7.7.7.7.6.7.7.7.7.6.7.7.7.7.7.6.7.7.7.7.7.7.7.7.6.7.7.7.6.7.6.6.7.7.7.7.6.6.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.6.7.6.7.7.7.6.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.5.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.6.7.6.7.6.7.6.7.6.7.7.7.6.7.7.7.7.6.7.6.7.7.7.7.6.7.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.7.7.7.7.6.7.7.7.7.7.6.7.6.7.7.7.7.6.7.7.6.7.6.7.6.7.7.6.7.7.7.7.7.6.7.7.7.7.7.6.7.7.7.7.7.7.6.7.7.7.7.7.6.6.7.7.6.6.7.6.7.6.7.7.7.7.7.6.6.7.7.6.7.7.7.7.7.7.7.6.6.7.7.6.7.7.7.6.7.6.7.6.7.7.7.6.7.7.7.7.7.7.7.7.6.7.7.7.7.7.7.6.7.7.7.6.7.6.7.7.7.7.7.7.6.7.7.7.7.7.7.7.6.7.7.7.6.7.7.6.7.7.7.6.7.6.7.6.7.6.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.6.7.6.7.7.7.7.7.6.7.7.7.7.7.6.7.7.6.7.7.7.7.7.6.7.6.7.6.", -"7.7.7.6.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.7.5.7.7.5.7.6.7.7.6.7.6.7.6.7.6.7.6.7.7.6.7.7.7.6.7.7.7.6.7.7.6.7.7.7.6.7.7.7.7.7.7.7.7.6.7.7.7.6.7.7.7.7.7.6.6.7.7.7.6.7.7.6.7.6.7.7.7.7.7.6.7.6.7.6.7.7.7.7.6.7.6.6.7.6.7.6.7.7.7.6.7.6.7.7.7.6.6.7.7.7.7.6.7.7.5.7.7.7.7.6.7.7.7.6.7.7.6.7.7.7.7.6.7.6.7.7.7.6.6.7.7.7.7.7.6.7.7.6.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.6.7.7.7.6.7.6.6.7.6.7.7.7.7.6.7.7.7.6.7.7.7.7.7.7.7.7.7.6.7.6.7.7.7.7.6.7.7.7.7.7.6.7.6.7.7.6.7.6.7.6.7.6.7.6.7.7.6.6.7.7.7.7.7.7.6.7.7.7.6.7.7.7.7.7.7.6.7.7.6.7.7.7.7.7.7.7.7.7.7.7.6.7.6.7.6.7.7.7.7.6.7.7.7.7.7.7.7.6.7.6.7.7.7.7.6.7.6.7.7.7.6.7.6.7.7.7.6.7.6.7.7.6.7.6.7.7.6.7.6.7.6.7.7.7.6.6.7.7.6.7.7.7.7.7.6.7.6.7.6.7.7.6.7.6.7.6.7.6.6.6.7.7.7.6.7.7.7.6.7.7.7.7.7.7.7.7.6.7.7.7.7.6.7.7.7.7.7.6.7.7.6.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.6.7.7.7.7.7.7.7.7.7.7.7.7.7.7.6.7.7.7.6.7.7.7.7.7.7.6.7.7.7.6.7.7.7.6.7.7.7.6.7.7.6.7.7.6.7.7.6.7.6.7.7.7.6.7.6.7.7.6.7.6.7.7.7.7.7.7.6.7.7.7.6.", -"6.6.7.7.7.7.6.7.7.7.7.7.5.7.7.5.6.7.6.7.7.6.6.7.7.7.6.6.6.6.6.7.6.7.6.6.7.7.6.7.7.7.7.6.7.7.7.7.6.7.7.6.6.7.7.7.7.6.7.7.7.7.6.7.7.6.6.7.6.7.6.7.7.6.6.7.6.7.7.6.7.6.6.6.6.7.6.7.7.6.6.7.6.7.6.6.6.7.7.7.6.7.6.7.7.6.6.7.7.6.6.7.7.7.6.7.6.7.6.6.7.6.7.7.7.7.7.7.7.7.6.7.6.7.7.7.6.6.7.7.7.7.6.7.7.7.6.7.7.7.7.5.7.7.6.7.6.7.6.7.7.6.6.6.7.6.6.7.7.6.6.7.7.7.6.6.6.7.7.6.7.7.6.7.6.6.7.6.6.7.6.7.7.7.6.7.6.6.7.7.7.6.7.7.7.7.7.7.6.7.6.7.7.6.6.7.7.7.6.7.6.6.6.7.6.6.7.7.7.7.6.7.6.7.5.7.7.6.6.7.6.7.7.6.6.7.7.7.7.6.7.7.7.7.6.7.7.6.6.6.6.7.6.7.7.6.6.7.6.7.6.6.6.7.7.6.7.7.6.7.6.6.7.6.6.7.6.7.6.7.7.6.6.7.7.6.7.6.7.6.6.6.7.6.6.6.7.7.7.7.6.7.6.7.7.7.6.7.6.7.6.7.7.6.6.7.7.7.6.6.7.7.7.7.6.7.6.7.7.7.6.7.6.7.7.7.6.7.7.6.6.7.7.7.7.7.6.7.6.7.7.6.6.7.7.7.7.7.7.6.7.6.7.7.6.7.7.6.6.6.6.7.6.6.7.7.6.7.6.6.7.7.7.7.7.6.7.6.6.7.7.6.7.6.6.6.7.6.6.6.6.7.6.7.6.6.7.7.6.7.6.6.7.7.7.6.6.7.6.6.7.6.6.7.6.7.7.6.6.7.7.7.6.7.6.6.6.7.7.6.6.6.6.7.6.7.7.6.6.7.6.7.6.6.6.7.6.7.6.7.7.6.6.7.7.6.7.6.7.6.7.7.6.7.7.6.7.7.7.7.6.7.6.7.7.7.6.6.7.7.7.7.6.7.7.6.7.6.6.7.6.7.", -"6.6.7.6.6.6.6.6.5.7.7.5.6.7.7.5.7.6.6.6.6.6.7.6.6.6.6.7.6.7.7.6.6.6.6.7.6.6.6.6.5.7.6.7.6.7.6.7.7.6.6.6.6.7.6.6.6.6.7.6.6.6.6.6.6.6.6.7.7.6.6.6.6.6.6.7.7.6.6.6.6.6.6.7.7.6.6.6.6.6.6.7.7.6.6.6.6.7.6.6.6.7.6.6.6.7.6.6.6.6.7.6.6.6.6.7.7.6.6.7.6.7.6.6.7.6.6.6.6.6.7.6.6.7.6.6.6.6.7.6.6.6.6.6.5.7.7.7.6.7.6.7.6.6.7.6.6.7.6.6.7.6.7.6.6.7.7.6.6.6.6.7.7.6.6.6.6.7.6.6.6.6.7.6.7.6.6.6.7.6.6.6.6.6.6.6.6.7.7.6.6.6.7.6.7.7.5.7.7.6.6.6.6.6.7.6.6.6.6.6.6.7.7.6.6.6.7.6.6.6.6.6.7.6.6.7.7.7.6.7.7.6.6.6.6.7.6.6.6.6.7.6.6.6.6.6.6.6.6.7.7.6.6.6.6.6.6.7.7.6.6.6.6.7.6.6.6.6.7.6.7.6.6.6.7.6.6.6.6.7.6.7.6.7.6.6.6.7.6.6.7.6.6.7.6.6.7.6.6.6.6.6.6.7.6.6.6.7.6.6.7.6.6.6.6.7.6.6.6.7.7.6.6.6.6.7.6.7.6.6.6.6.6.7.6.6.7.6.6.6.7.6.6.7.6.6.6.7.6.6.6.6.6.7.7.6.6.6.7.6.6.6.6.6.7.6.6.6.6.7.7.6.6.6.6.6.7.6.6.6.6.6.6.6.6.7.7.6.6.7.6.7.6.6.7.6.6.7.6.7.7.6.6.6.6.7.6.6.6.6.6.7.7.6.6.6.7.6.6.7.6.6.7.6.6.6.6.6.7.6.6.6.6.6.6.7.7.6.6.6.6.7.7.6.6.6.6.6.6.7.7.6.6.6.6.7.6.6.7.6.6.6.6.7.6.6.6.7.6.6.5.7.7.7.6.7.5.7.6.6.7.6.6.7.6.6.6.6.7.6.6.6.6.6.5.7.6.7.6.7.6.7.", -"6.6.6.6.6.6.6.6.7.5.5.7.6.6.6.7.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.7.5.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.7.5.5.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.7.5.5.7.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.7.6.6.5.5.7.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.7.5.5.6.6.5.7.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.", -"6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.5.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.5.6.6.6.5.6.6.6.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.5.6.6.6.6.6.6.6.5.6.5.6.6.6.6.5.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.6.5.6.6.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.5.5.6.5.6.6.6.6.6.6.6.6.6.6.5.6.7.5.6.6.6.5.6.5.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.5.6.6.6.5.6.6.5.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.5.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.5.6.6.5.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.5.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.5.6.6.6.6.6.5.6.6.5.6.6.6.5.6.6.6.6.6.6.5.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.5.6.6.5.6.5.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.5.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.5.6.6.6.5.6.5.6.6.6.6.6.6.6.", -"6.6.5.6.5.6.6.5.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.5.6.6.6.6.5.6.6.6.6.6.5.6.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.5.6.6.5.6.6.5.6.6.6.6.6.6.6.6.6.6.5.6.6.5.6.5.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.5.6.6.5.7.6.6.6.6.6.6.6.6.6.6.6.6.6.6.7.5.5.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.5.6.6.6.5.6.6.5.6.6.5.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.5.5.6.6.6.6.6.6.5.6.6.6.6.6.5.6.6.6.5.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.5.6.6.6.6.6.6.5.6.6.6.6.6.5.6.6.5.6.5.6.5.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.5.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.6.6.6.6.5.6.5.6.6.6.6.5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.5.6.6.", -"6.5.6.5.6.6.6.5.5.5.6.5.5.6.5.6.5.6.6.6.6.5.6.5.6.6.5.6.6.6.5.6.5.6.5.6.6.6.5.6.5.6.6.5.6.6.6.5.5.6.6.6.6.5.6.5.6.6.6.5.6.6.5.6.6.6.6.6.5.6.5.6.5.6.5.6.5.6.5.6.5.6.5.6.5.5.6.5.5.5.6.5.6.6.6.6.5.5.6.5.5.6.5.6.6.6.5.6.5.6.5.6.6.6.6.5.6.5.6.5.5.6.6.6.5.6.5.6.6.5.6.6.6.5.6.6.5.6.5.6.6.6.6.6.6.5.6.5.6.6.6.5.6.5.6.6.6.5.6.5.6.5.6.5.5.6.5.6.5.6.6.5.5.5.6.6.5.6.5.6.5.6.6.5.6.5.6.5.5.6.5.6.6.6.6.5.6.5.6.6.6.5.6.6.5.6.5.6.5.6.6.6.6.5.6.5.6.5.5.6.6.5.6.5.6.5.5.6.6.6.5.6.5.6.6.5.6.6.6.5.5.6.6.6.6.5.6.5.6.6.6.5.6.6.5.6.6.5.6.5.5.6.5.6.5.5.6.5.5.6.5.6.5.5.6.6.5.6.5.5.6.5.6.5.5.6.5.6.5.6.6.6.6.6.6.5.6.5.5.6.5.6.6.6.6.5.5.5.5.6.5.6.5.5.6.5.6.6.5.6.5.6.6.6.6.5.6.5.6.5.6.6.5.6.5.6.5.6.6.5.6.5.5.6.6.5.6.5.5.6.6.6.5.5.6.5.6.6.6.6.6.6.6.6.5.6.5.6.6.5.6.5.5.6.5.6.6.5.6.5.5.6.5.6.5.6.5.6.5.6.5.6.5.6.6.5.6.5.6.5.6.6.5.6.5.6.5.6.6.6.6.5.6.5.6.6.6.6.6.5.6.5.6.5.5.6.6.6.5.6.5.6.6.6.6.6.6.5.6.5.6.6.6.5.6.5.6.5.6.5.6.5.5.6.5.6.6.6.6.6.5.6.5.6.5.6.5.6.5.5.6.5.5.5.6.5.6.6.6.6.6.5.6.5.6.6.6.6.6.5.6.5.5.6.6.6.5.6.5.6.5.6.6.6.6.5.6.5.6.5.5.6.", -"5.6.5.6.5.5.6.6.5.6.6.5.6.5.6.5.6.5.5.5.6.5.6.5.5.5.5.5.5.6.5.6.5.6.5.5.5.5.6.5.6.5.6.5.5.5.5.6.6.5.5.5.6.5.6.5.5.5.5.6.5.5.6.6.5.5.5.5.6.5.6.5.6.5.6.5.5.6.5.6.5.6.5.6.5.6.5.6.5.6.5.6.5.5.5.5.5.6.5.6.6.5.6.5.5.6.5.6.5.5.6.5.5.5.6.5.5.6.5.6.5.5.5.6.5.6.5.5.6.5.5.5.5.6.5.6.5.6.5.5.5.5.5.5.6.5.6.5.5.5.5.6.6.5.5.5.5.6.5.5.5.6.5.6.6.5.6.5.6.5.5.6.5.6.6.5.5.6.6.5.6.5.5.6.5.6.5.6.6.5.6.5.5.5.6.5.6.5.5.5.5.6.5.6.5.6.5.5.6.5.5.5.6.5.5.6.5.6.5.5.5.6.5.6.5.6.5.5.5.5.6.5.6.5.6.5.5.5.5.6.6.5.5.5.6.5.6.5.5.5.5.6.5.5.6.6.5.6.5.6.6.5.6.5.6.6.5.6.5.6.6.5.5.6.6.5.6.5.6.6.5.6.5.6.6.5.6.5.5.5.5.5.5.5.6.5.5.6.6.5.6.5.5.6.5.6.5.6.6.5.6.5.6.6.5.6.5.5.6.5.6.5.5.5.6.5.5.6.5.6.5.5.6.5.6.5.6.5.5.6.5.6.5.6.5.6.5.6.5.5.5.6.5.6.5.6.5.5.5.5.5.5.5.5.5.6.5.6.5.6.5.6.6.5.6.5.5.6.5.6.6.5.6.5.6.5.6.5.6.5.6.5.6.5.5.6.5.6.5.6.5.5.6.5.6.5.6.5.5.5.6.5.6.5.5.5.5.5.5.6.5.6.5.6.5.5.5.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.6.5.6.5.5.5.6.5.6.6.5.6.5.5.5.5.5.6.5.6.5.5.6.5.6.5.6.5.6.5.6.5.6.5.5.5.5.6.5.6.5.5.5.5.5.5.6.5.6.5.5.5.5.6.5.6.5.6.5.5.5.5.6.5.6.5.6.5.5.", -"5.5.5.6.5.5.5.6.5.5.5.5.5.6.6.5.5.6.5.5.5.5.5.6.5.5.5.5.5.5.5.6.6.5.6.4.6.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.6.6.4.5.5.5.5.5.6.5.5.5.5.5.5.5.6.6.5.5.6.5.5.5.6.5.5.5.6.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.6.5.6.4.6.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.6.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.6.6.4.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.6.6.5.6.4.6.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.6.6.4.5.5.5.5.5.6.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.6.4.6.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.6.6.4.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.6.5.5.5.6.5.5.5.5.5.5.6.5.6.4.6.5.5.5.6.5.5.5.5.5.5.6.5.5.5.5.6.5.5.5.5.5.6.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.6.6.4.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.", -"5.6.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.6.6.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.4.6.6.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.6.5.5.5.5.6.5.5.5.5.5.5.5.5.4.6.4.6.6.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.7.5.5.5.5.5.6.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.4.6.6.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.5.5.5.7.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.6.6.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.4.6.6.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.6.5.5.6.5.6.5.5.5.5.5.5.5.4.6.4.6.6.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.4.6.6.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.6.5.6.5.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.5.5.5.6.5.4.6.4.6.6.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.7.5.5.5.5.5.6.5.5.5.5.5.5.5.5.6.5.5.6.5.5.5.5.5.5.5.4.6.6.5.6.5.6.5.5.5.5.5.6.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.", -"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.5.5.5.5.5.5.5.5.5.5.6.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.5.5.5.5.5.5.5.5.5.5.6.4.5.5.5.5.5.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.5.5.5.5.5.5.5.5.5.5.6.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.5.5.5.5.5.5.5.5.5.5.6.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.6.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.4.6.4.5.5.5.5.5.5.5.5.5.5.6.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", -"5.5.5.4.5.5.5.5.5.4.5.5.5.5.5.4.5.4.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.4.5.5.4.5.5.4.5.5.5.4.5.5.5.4.5.5.4.5.5.5.5.5.5.5.5.4.5.4.5.5.5.5.5.4.5.5.5.5.4.5.5.5.5.5.5.5.4.5.4.4.5.5.5.5.5.4.5.4.5.5.5.5.4.5.5.5.5.4.5.4.5.5.5.5.4.5.4.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.4.5.5.4.5.5.4.5.5.5.4.5.5.5.4.5.5.5.4.5.4.5.5.5.5.5.5.5.4.5.5.5.5.5.4.5.5.5.5.4.5.5.5.5.5.5.5.4.5.4.4.5.5.5.5.5.4.5.4.5.5.5.5.4.5.4.5.5.4.5.5.4.5.5.5.5.5.5.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.4.5.5.4.5.5.4.5.5.5.4.5.5.5.4.5.5.4.5.5.5.5.5.5.5.5.4.5.4.5.5.5.5.5.4.5.5.5.5.4.5.5.5.5.5.5.5.4.5.4.4.5.5.5.5.5.4.5.4.5.5.5.4.5.4.5.5.5.4.5.4.5.5.5.5.5.5.4.5.5.4.5.5.5.5.5.5.5.5.5.5.5.5.4.5.5.4.5.5.4.5.5.4.5.5.5.4.5.5.5.4.5.5.4.5.5.5.5.5.5.5.5.4.5.4.5.5.5.5.5.4.5.5.5.5.4.5.5.5.5.5.5.5.4.5.4.4.5.5.5.5.5.4.5.4.5.5.5.4.5.4.5.4.5.5.5.4.5.5.5.5.5.4.5.5.5.4.5.5.4.5.5.5.5.5.5.5.5.5.4.5.5.4.5.5.4.5.5.4.5.5.5.4.5.5.5.4.5.5.5.4.5.4.5.5.5.5.5.5.5.4.5.5.5.5.5.4.5.5.5.5.4.5.5.5.5.5.5.5.4.5.4.4.5.5.5.5.5.4.5.4.5.5.5.5.5.5.5.5.5.5.4.5.5.5.5.5.5.3.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.", -"5.4.4.5.4.4.5.4.4.5.4.4.5.4.4.5.4.4.5.4.4.5.5.4.5.5.4.5.5.4.4.5.4.5.4.4.5.4.4.4.4.4.4.5.4.4.4.5.4.5.4.5.4.4.5.4.5.3.5.5.4.5.5.4.5.5.4.5.5.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.5.5.4.4.4.5.4.4.4.5.5.4.4.5.4.4.5.4.5.4.4.5.4.5.4.4.4.5.5.4.4.5.5.4.4.5.4.5.5.5.5.3.4.5.4.4.5.4.4.4.4.4.4.5.4.4.4.5.5.4.4.5.4.4.5.4.4.5.4.4.5.4.4.5.5.5.4.5.5.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.5.5.4.4.4.5.4.4.4.5.5.4.4.5.4.4.5.4.5.4.4.5.4.5.4.4.5.5.5.4.5.4.4.4.5.5.4.5.5.5.3.5.4.5.4.4.5.4.4.4.4.4.4.5.4.4.4.5.4.5.4.5.4.4.5.4.5.3.5.5.4.5.5.4.5.5.4.5.5.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.5.5.4.4.4.5.4.4.4.5.4.5.4.4.4.5.4.4.5.4.4.5.4.5.4.4.4.5.5.4.5.4.4.4.4.5.4.4.5.5.5.4.4.5.4.4.5.4.4.4.4.4.4.5.4.4.4.5.4.5.4.5.4.4.5.4.5.3.5.5.4.5.5.4.5.5.4.5.5.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.5.5.4.4.4.5.4.4.4.5.4.5.5.4.5.5.4.5.5.4.5.5.4.5.5.4.4.5.5.4.5.4.4.5.4.5.5.4.5.5.3.5.4.5.4.4.5.4.4.4.4.4.4.5.4.4.4.5.5.4.4.5.4.4.5.4.4.5.4.4.5.4.4.5.5.5.4.5.5.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.5.5.4.4.4.5.4.4.4.5.4.5.4.4.5.4.5.4.3.5.5.4.5.5.5.5.5.5.5.3.5.5.5.3.5.3.5.3.5.5.3.5.", -"4.4.5.4.4.5.5.4.4.5.5.4.4.4.5.4.4.5.4.5.5.4.4.4.4.3.5.5.4.5.5.4.5.4.4.5.4.5.4.4.4.5.5.4.4.5.4.5.4.4.5.4.5.4.4.5.5.5.5.3.5.4.4.5.4.4.4.4.4.5.5.4.5.4.4.5.4.4.4.4.4.5.5.4.4.4.4.4.4.5.5.4.4.4.5.4.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.4.4.4.5.5.4.4.4.4.4.5.4.5.3.5.5.5.4.4.5.4.5.4.4.4.5.5.4.4.5.4.5.4.5.4.4.4.5.5.4.4.5.5.4.4.4.5.4.4.4.4.4.4.5.5.4.5.4.4.5.4.4.4.4.4.5.5.4.4.4.4.4.4.5.5.4.4.4.5.4.4.4.5.4.5.4.4.5.4.5.5.4.4.4.5.5.5.3.4.5.5.4.5.4.4.3.5.5.3.5.5.5.5.4.4.5.4.5.4.4.4.5.5.4.4.5.4.5.4.4.5.4.5.4.4.5.5.5.5.3.5.4.4.5.4.4.4.4.4.5.5.4.5.4.4.5.4.4.4.4.4.5.5.4.4.4.4.4.4.5.5.4.4.4.5.4.4.4.5.5.5.4.4.5.4.5.5.4.4.4.5.5.4.4.4.5.5.4.5.4.4.4.5.5.5.3.3.5.5.4.4.5.4.5.4.4.4.5.5.4.4.5.4.5.4.4.5.4.5.4.4.5.5.5.5.3.5.4.4.5.4.4.4.4.4.5.5.4.5.4.4.5.4.4.4.4.4.5.5.4.4.4.4.4.4.5.5.4.4.4.5.4.5.4.4.5.4.4.4.4.4.4.4.4.5.4.4.4.5.4.4.4.5.4.5.4.5.4.4.5.3.5.4.5.5.4.4.5.4.5.4.4.4.5.5.4.4.5.4.5.4.5.4.4.4.5.5.4.4.5.5.4.4.4.5.4.4.4.4.4.4.5.5.4.5.4.4.5.4.4.4.4.4.5.5.4.4.4.4.4.4.5.5.4.4.4.5.4.4.4.5.5.5.4.4.5.5.4.4.5.3.3.5.3.5.3.5.5.3.5.5.5.5.5.5.5.3.5.5.5.", -"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.3.5.3.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.3.5.3.5.5.4.4.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.4.4.5.3.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.5.5.4.3.5.4.5.4.4.5.3.3.5.3.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.3.5.3.5.5.4.4.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.4.5.3.5.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.3.5.3.5.5.4.4.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.4.4.4.5.3.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.5.5.5.5.5.5.3.5.3.5.3.5.3.3.5.3.5.3.5.3.5.", -"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.4.3.5.4.4.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.4.4.3.3.4.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.5.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.4.4.4.3.4.5.3.4.3.5.5.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.4.4.3.3.4.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.3.5.3.5.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.4.4.3.3.4.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.5.3.4.3.5.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.5.3.4.5.3.3.3.5.3.5.3.5.3.5.3.5.4.3.5.3.5.5.3.3.", -"4.4.3.4.3.4.4.4.3.3.4.4.4.4.3.3.3.4.4.4.4.4.4.3.3.3.3.4.4.4.3.4.4.4.3.4.3.4.3.4.4.3.4.3.4.3.4.3.4.4.4.3.3.4.4.4.3.3.4.4.4.3.4.4.4.3.4.3.4.3.3.5.3.4.3.4.4.3.3.4.4.4.4.3.4.4.4.3.3.4.4.4.4.4.4.3.3.3.4.4.3.4.4.4.3.3.4.4.4.4.3.3.3.4.4.4.4.4.4.3.3.4.3.4.4.4.3.4.4.4.3.4.3.4.3.4.4.3.4.3.4.3.4.3.4.4.3.4.4.4.4.4.3.4.4.3.4.4.3.3.4.4.3.4.4.4.3.4.3.4.3.4.4.3.3.4.4.4.4.3.4.4.4.3.3.4.4.4.4.4.4.3.4.4.4.3.4.4.3.4.3.3.4.3.4.4.3.3.3.3.3.5.3.3.3.5.3.4.3.5.3.4.3.4.4.4.3.4.3.4.3.4.4.3.4.3.4.3.4.3.4.4.4.3.3.4.4.4.3.3.4.4.4.3.4.4.4.3.4.3.4.3.3.5.3.4.3.4.4.3.3.4.4.4.4.3.4.4.4.3.3.4.4.4.4.4.4.3.4.3.4.4.4.3.4.4.4.4.3.4.3.4.3.3.4.4.4.3.4.3.3.4.3.4.4.3.4.4.4.3.4.4.3.4.3.4.3.4.4.3.4.3.4.3.4.3.4.4.4.3.3.4.4.4.3.3.4.4.4.3.4.4.4.3.4.3.4.3.3.5.3.4.3.4.4.3.3.4.4.4.4.3.4.4.4.3.3.4.4.4.4.4.4.3.3.4.4.3.4.3.4.4.4.4.3.4.3.4.4.4.4.4.4.3.4.3.3.4.4.3.4.3.4.4.4.3.4.4.3.4.3.4.3.4.4.3.4.3.4.3.4.3.4.4.3.4.4.4.4.4.3.4.4.3.4.4.3.3.4.4.3.4.4.4.3.4.3.4.3.4.4.3.3.4.4.4.4.3.4.4.4.3.3.4.4.4.4.4.4.3.4.3.4.3.5.3.3.5.3.3.3.5.5.3.3.3.5.3.3.3.5.3.3.3.3.4.3.3.4.4.4.3.", -"4.3.3.4.4.4.3.4.4.4.4.3.3.4.4.4.4.4.3.3.3.3.4.3.4.4.3.5.3.4.3.4.3.4.4.3.3.4.4.3.4.4.3.4.4.4.3.4.4.3.3.4.3.5.3.4.4.4.4.3.3.4.3.4.3.5.4.3.3.5.3.3.4.4.4.3.3.4.4.3.3.4.4.3.4.3.4.4.4.4.2.4.4.3.4.4.4.4.4.3.4.3.3.4.4.4.4.3.3.4.4.4.4.4.3.3.3.3.4.3.4.3.3.5.3.4.3.4.3.4.4.3.3.4.4.3.4.4.3.4.4.4.3.4.4.3.3.4.2.4.4.3.4.3.3.4.3.4.4.4.4.3.4.4.3.4.3.4.4.4.4.3.3.4.4.3.3.4.4.3.4.3.4.4.4.4.2.4.4.3.4.4.4.3.3.4.4.4.4.3.4.4.3.4.3.4.4.4.5.5.3.3.5.5.3.3.4.3.3.5.3.4.3.4.3.4.4.3.3.4.4.3.4.4.3.4.4.4.3.4.4.3.3.4.3.5.3.4.4.4.4.3.3.4.3.4.3.5.4.3.3.5.3.3.4.4.4.3.3.4.4.3.3.4.4.3.4.3.4.4.4.4.2.4.4.3.4.4.4.4.4.3.4.3.4.3.3.4.3.4.4.4.4.4.3.3.4.4.4.4.4.3.3.4.3.5.4.3.4.4.3.4.4.3.3.4.4.3.4.4.3.4.4.4.3.4.4.3.3.4.3.5.3.4.4.4.4.3.3.4.3.4.3.5.4.3.3.5.3.3.4.4.4.3.3.4.4.3.3.4.4.3.4.3.4.4.4.4.2.4.4.3.4.4.4.3.3.4.3.4.4.3.3.4.3.4.4.4.3.4.3.3.4.4.4.4.4.3.3.4.3.4.4.3.4.4.3.4.4.3.3.4.4.3.4.4.3.4.4.4.3.4.4.3.3.4.2.4.4.3.4.3.3.4.3.4.4.4.4.3.4.4.3.4.3.4.4.4.4.3.3.4.4.3.3.4.4.3.4.3.4.4.4.4.2.4.4.3.4.4.4.4.3.4.3.3.5.3.3.5.3.3.3.5.5.3.3.3.5.5.3.3.5.5.4.3.5.3.4.3.4.4.", -"3.4.4.3.3.3.3.3.4.3.3.3.4.3.3.3.3.4.4.4.4.3.3.3.3.5.3.3.3.5.3.4.4.3.3.4.4.4.3.4.3.4.3.4.3.4.3.4.3.4.4.3.4.3.4.3.3.4.3.4.3.4.4.3.3.5.3.4.4.3.3.5.4.3.3.3.4.4.4.4.4.3.4.4.4.3.3.3.4.3.4.4.3.3.4.3.3.4.3.4.3.4.3.3.4.3.3.3.4.3.3.3.3.4.4.4.4.3.3.3.3.5.3.3.3.5.4.3.4.3.3.4.4.4.3.4.3.4.3.4.3.4.3.4.3.4.4.3.3.4.4.3.3.4.4.3.3.4.3.4.3.4.4.3.3.4.3.4.4.3.3.3.4.4.4.4.4.3.4.4.4.3.3.3.4.3.4.4.3.3.4.3.3.4.4.3.4.2.3.4.4.4.4.4.4.3.4.3.3.3.5.3.3.3.3.3.3.5.3.3.3.5.4.3.4.3.3.4.4.4.3.4.3.4.3.4.3.4.3.4.3.4.4.3.4.3.4.3.3.4.3.4.3.4.4.3.3.5.3.4.4.3.3.5.4.3.3.3.4.4.4.4.4.3.4.4.4.3.3.3.4.3.4.4.3.3.4.3.4.3.3.3.3.4.3.3.3.4.3.4.4.3.3.3.3.4.3.4.3.3.3.3.3.3.4.3.3.5.3.3.4.3.3.4.4.4.3.4.3.4.3.4.3.4.3.4.3.4.4.3.4.3.4.3.3.4.3.4.3.4.4.3.3.5.3.4.4.3.3.5.4.3.3.3.4.4.4.4.4.3.4.4.4.3.3.3.4.3.4.4.3.3.4.3.3.4.4.3.3.4.3.3.3.4.3.4.3.3.3.3.3.4.4.3.3.3.3.3.4.3.4.4.4.3.3.3.4.3.3.4.4.4.3.4.3.4.3.4.3.4.3.4.3.4.4.3.3.4.4.3.3.4.4.3.3.4.3.4.3.4.4.3.3.4.3.4.4.3.3.3.4.4.4.4.4.3.4.4.4.3.3.3.4.3.4.4.3.3.4.3.4.4.4.4.3.5.3.3.3.3.3.5.3.3.3.3.3.3.3.3.3.3.3.3.3.3.5.3.5.3.3.3.", -"3.3.4.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.4.4.2.4.3.3.3.4.3.3.3.4.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.4.2.3.3.4.2.4.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.4.4.2.4.3.3.3.4.3.3.3.4.3.4.3.3.4.3.3.4.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.4.2.3.3.4.2.4.3.3.4.3.4.3.3.4.2.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.4.4.2.4.3.3.3.4.3.3.3.4.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.4.2.3.3.4.2.4.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.4.3.3.3.3.3.3.3.4.3.3.3.3.3.4.4.2.4.3.3.3.4.3.3.3.4.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.4.2.3.3.4.2.4.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.4.3.3.3.4.3.3.3.3.3.4.4.2.4.3.3.3.4.3.3.3.4.3.4.3.3.4.3.3.4.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.4.2.3.3.4.2.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.5.3.3.3.3.3.4.3.3.3.4.3.3.", -"3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.", -"3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.2.3.4.2.4.2.3.3.2.3.3.3.3.3.3.2.3.2.3.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.3.3.3.2.3.3.3.3.2.3.3.3.2.3.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.2.3.4.2.4.2.3.3.2.3.3.3.3.3.3.2.3.2.3.2.4.2.3.2.2.3.3.2.3.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.3.3.3.2.3.2.3.2.2.3.3.2.3.3.3.3.3.3.2.3.3.3.2.3.3.3.3.2.3.3.3.3.2.3.3.3.2.3.4.2.4.2.3.3.2.3.3.3.3.3.3.2.3.2.3.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.3.3.3.3.2.3.3.3.2.3.4.2.4.2.3.3.2.3.3.3.3.3.3.2.3.2.3.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.2.3.3.3.2.3.3.3.3.3.3.3.3.3.2.3.3.3.2.3.4.2.4.2.3.3.2.3.3.3.3.3.3.2.3.2.3.2.4.2.3.2.2.3.3.2.3.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.2.3.3.3.2.3.3.2.3.2.2.3.2.3.3.3.3.2.3.3.3.2.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.2.3.3.2.3.2.3.2.3.", -"3.3.3.3.3.3.2.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.3.3.3.3.3.3.2.4.2.3.3.3.3.3.3.2.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.2.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.2.2.3.3.2.3.3.3.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.3.3.3.3.3.3.2.4.2.3.3.3.3.3.3.2.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.2.3.3.3.3.3.2.3.3.3.2.3.2.3.3.3.3.2.2.3.3.2.3.3.3.3.3.3.", -"3.3.3.3.2.3.3.2.3.3.2.3.3.2.2.3.2.3.2.3.3.2.2.3.2.2.2.3.2.3.3.3.2.3.2.2.3.2.3.2.3.3.2.3.3.2.3.3.3.2.2.2.2.2.2.3.3.2.2.2.2.3.2.2.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.3.3.3.3.2.3.3.2.3.3.2.3.2.2.2.3.2.2.3.3.3.2.2.3.2.2.2.3.2.3.3.3.2.3.2.2.3.2.3.2.3.3.2.3.3.2.3.3.2.3.2.2.2.2.2.3.3.2.2.3.2.2.2.3.2.3.3.2.2.3.2.2.3.2.2.2.3.2.2.3.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.3.2.2.2.2.2.2.3.2.2.2.3.2.3.3.2.2.2.3.2.2.3.2.2.3.2.3.2.3.3.2.3.2.3.2.2.3.2.3.2.3.3.2.3.3.2.3.3.3.2.2.2.2.2.2.3.3.2.2.2.2.3.2.2.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.3.3.2.2.2.3.2.2.3.3.2.3.2.2.2.3.2.2.3.3.2.3.2.2.3.2.3.2.3.3.3.3.2.3.2.2.3.2.3.2.3.3.2.3.3.2.3.3.3.2.2.2.2.2.2.3.3.2.2.2.2.3.2.2.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.2.3.2.2.2.3.2.2.3.3.3.2.2.3.3.2.2.2.3.3.2.3.2.2.3.2.3.2.3.3.3.3.2.3.2.2.3.2.3.2.3.3.2.3.3.2.3.3.2.3.2.2.2.2.2.3.3.2.2.3.2.2.2.3.2.3.3.2.2.3.2.2.3.2.2.2.3.2.2.3.2.3.2.3.2.2.3.2.3.2.2.2.3.2.2.3.3.3.2.3.3.2.2.3.3.3.3.2.2.3.3.2.3.3.2.3.3.2.3.3.2.3.2.3.2.2.3.2.", -"2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.2.3.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.3.2.2.2.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.3.2.2.2.2.2.3.2.2.3.2.2.2.2.3.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.3.2.2.2.2.2.2.2.3.", -"2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.", -"2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.", -"2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.2.1.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.2.2.1.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.2.1.2.2.2.1.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.1.2.1.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.2.2.1.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.2.2.1.2.1.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.2.2.1.2.2.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.2.1.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.1.2.1.2.2.2.2.2.1.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.2.2.2.2.1.2.2.", -"2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.1.2.2.2.2.1.2.2.2.2.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.1.2.2.1.2.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.1.2.2.2.2.2.2.1.2.2.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.1.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.1.2.1.2.2.2.1.1.1.1.1.2.2.2.1.2.2.1.2.2.1.2.2.1.2.1.2.2.2.1.1.1.1.2.2.2.1.2.2.2.2.2.1.2.2.2.2.2.2.1.", -"1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.1.2.2.1.1.1.2.2.1.1.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.1.1.2.1.1.1.2.2.1.2.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.1.1.2.1.1.1.2.2.1.2.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.2.1.1.2.2.1.1.2.1.2.1.2.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.2.1.2.1.2.2.1.1.1.2.1.2.1.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.1.1.2.1.1.1.2.2.1.2.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.2.1.1.2.2.1.1.2.1.2.1.2.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.1.1.2.1.1.1.2.2.1.2.2.1.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.2.1.1.2.2.1.1.2.1.2.1.2.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.1.1.2.2.1.1.2.2.1.1.2.1.2.1.2.2.1.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.2.2.1.2.1.1.2.1.1.1.2.1.1.1.1.2.2.2.2.2.1.1.2.2.2.1.2.1.2.1.2.", -"2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.1.2.2.1.1.2.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.2.1.1.2.1.2.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.2.1.1.1.1.2.2.1.2.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.1.2.2.1.1.2.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.2.1.1.1.2.2.2.1.2.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.1.2.2.2.2.2.2.2.1.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.2.1.1.1.1.2.2.1.2.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.1.2.1.1.1.1.2.2.1.2.2.1.1.2.2.1.1.2.1.2.1.1.1.1.2.2.1.2.1.1.2.2.2.2.1.2.2.2.2.2.2.1.2.1.1.1.1.1.2.2.1.1.1.1.2.2.1.2.2.1.1.2.2.1.", -"1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.2.1.2.1.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.2.1.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.2.1.2.1.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.1.1.1.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.2.1.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.2.1.1.2.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.2.1.2.1.2.1.1.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.2.1.2.1.1.1.1.1.2.1.1.2.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.", -"1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1." -}; diff --git a/mixer/icons/icon-large.svg b/mixer/icons/icon-large.svg deleted file mode 100644 index 8b251a5..0000000 --- a/mixer/icons/icon-large.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mixer/icons/icon-small.svg b/mixer/icons/icon-small.svg deleted file mode 120000 index 1d9c2c6..0000000 --- a/mixer/icons/icon-small.svg +++ /dev/null @@ -1 +0,0 @@ -icon-large.svg \ No newline at end of file diff --git a/mixer/non-mixer.desktop.in b/mixer/non-mixer.desktop.in deleted file mode 100644 index 61e4221..0000000 --- a/mixer/non-mixer.desktop.in +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Name=Non Mixer -Comment=Modular Digital Audio Workstation - Mixer -Comment[fr]=Station de travail audio-numérique modulaire - Mixeur -Exec=@BIN_PATH@/non-mixer -Terminal=false -Type=Application -Icon=non-mixer -Categories=AudioVideo;Audio; diff --git a/mixer/pixmaps/panner-plane-502x502.png b/mixer/pixmaps/panner-plane-502x502.png deleted file mode 100644 index 923d8db..0000000 Binary files a/mixer/pixmaps/panner-plane-502x502.png and /dev/null differ diff --git a/mixer/pixmaps/panner-plane-802x802.png b/mixer/pixmaps/panner-plane-802x802.png deleted file mode 100644 index d55d68c..0000000 Binary files a/mixer/pixmaps/panner-plane-802x802.png and /dev/null differ diff --git a/mixer/pixmaps/panner-plane-92x92.png b/mixer/pixmaps/panner-plane-92x92.png deleted file mode 100644 index b153e2c..0000000 Binary files a/mixer/pixmaps/panner-plane-92x92.png and /dev/null differ diff --git a/mixer/pixmaps/panner-sphere-502x502.png b/mixer/pixmaps/panner-sphere-502x502.png deleted file mode 100644 index 12356d3..0000000 Binary files a/mixer/pixmaps/panner-sphere-502x502.png and /dev/null differ diff --git a/mixer/pixmaps/panner-sphere-802x802.png b/mixer/pixmaps/panner-sphere-802x802.png deleted file mode 100644 index b63fca3..0000000 Binary files a/mixer/pixmaps/panner-sphere-802x802.png and /dev/null differ diff --git a/mixer/pixmaps/panner-sphere-92x92.png b/mixer/pixmaps/panner-sphere-92x92.png deleted file mode 100644 index dad8dc7..0000000 Binary files a/mixer/pixmaps/panner-sphere-92x92.png and /dev/null differ diff --git a/mixer/src/AUX_Module.C b/mixer/src/AUX_Module.C deleted file mode 100644 index d8aa58e..0000000 --- a/mixer/src/AUX_Module.C +++ /dev/null @@ -1,206 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include "AUX_Module.H" -#include "dsp.h" - -/* The purpose of this module is to provide auxiliary outputs, with - * gain. This allows one to create a 'send' type topology without - * having to use an extra strip to control the 'send' gain. */ - -AUX_Module::AUX_Module ( ) : JACK_Module ( false ) -{ - is_default( false ); - - _number = 0; - - { - Port p( this, Port::INPUT, Port::CONTROL, "Gain (dB)" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -70.0f; - p.hints.maximum = 6.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - log_create(); - - color( FL_DARK1 ); - - copy_label( "Aux" ); - - smoothing.sample_rate( sample_rate() ); -} - -AUX_Module::~AUX_Module ( ) -{ - configure_outputs(0); - delete (float*)control_input[0].buffer(); -} - - - -void -AUX_Module::get ( Log_Entry &e ) const -{ - e.add( ":number", number() ); - JACK_Module::get(e); -} - -void -AUX_Module::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! ( strcmp( s, ":number" ) ) ) - { - number( atoi(v) ); - } - } - - JACK_Module::set(e); -} - -void -AUX_Module::number ( int n ) -{ - _number = n; - - char s[10]; - snprintf( s, sizeof(s), "aux-%c", 'A' + n ); - prefix( s ); - snprintf( s, sizeof(s), "Aux (%c)", 'A' + n ); - copy_label( s ); -} - -void -AUX_Module::handle_sample_rate_change ( nframes_t n ) -{ - smoothing.sample_rate( n ); -} - -void -AUX_Module::process ( nframes_t nframes ) -{ - if ( unlikely( bypass() ) ) - { - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - { - if ( audio_input[i].connected() ) - buffer_fill_with_silence( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), nframes ); - } - } - else - { - float gt = DB_CO( control_input[0].control_value() ); - - sample_t gainbuf[nframes]; - - bool use_gainbuf = smoothing.apply( gainbuf, nframes, gt ); - - if ( unlikely( use_gainbuf ) ) - { - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - { - if ( audio_input[i].connected() ) - buffer_copy_and_apply_gain_buffer( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), (sample_t*)audio_input[i].buffer(), gainbuf, nframes ); - } - - } - else - { - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - { - if ( audio_input[i].connected() ) - buffer_copy_and_apply_gain( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), (sample_t*)audio_input[i].buffer(), nframes, gt ); - } - } - } -} - -void -AUX_Module::draw ( void ) -{ - int W = 5; - - child(0)->size( w() - W, h() ); - Module::draw_box(x(),y(),w() - W,h()); - Module::draw_label(x(),y(),w() - W,h()); - - Module *m = this; - - fl_color( fl_darker( FL_FOREGROUND_COLOR ) ); - - int spacing, offset; - - spacing = h() / m->ninputs(); - offset = spacing / 2; - for ( int i = m->ninputs(); i--; ) - { - int xi = offset + ( spacing * i ); - fl_rectf( m->x() + m->w() - W, m->y() + xi, W, 2 ); - } -} - -bool -AUX_Module::configure_outputs ( int n ) -{ - int on = audio_output.size(); - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - } - } - else - { - for ( int i = on; i > n; --i ) - { - audio_output.back().disconnect(); - audio_output.pop_back(); - } - } - - return true; -} - -bool -AUX_Module::configure_inputs ( int n ) -{ - bool b = JACK_Module::configure_inputs( n ); - - if ( b ) - { - return configure_outputs( n ); - } - - return false; -} diff --git a/mixer/src/AUX_Module.H b/mixer/src/AUX_Module.H deleted file mode 100644 index e422a54..0000000 --- a/mixer/src/AUX_Module.H +++ /dev/null @@ -1,61 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "JACK_Module.H" -#include "dsp.h" - -class AUX_Module : public JACK_Module -{ - int _number; - - Value_Smoothing_Filter smoothing; - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - -public: - - virtual const char *name ( void ) const { return "AUX"; } - - int can_support_inputs ( int n ) { return n > 0 ? n : -1; } - - virtual bool configure_outputs ( int n ); - virtual bool configure_inputs ( int n ); - - void number ( int n ); - int number ( void ) const { return _number; } - - AUX_Module ( ); - virtual ~AUX_Module ( ); - - LOG_CREATE_FUNC( AUX_Module ); - - virtual void handle_sample_rate_change ( nframes_t n ); - -protected: - - virtual void draw ( void ); - virtual void process ( nframes_t nframes ); - -}; - diff --git a/mixer/src/Chain.C b/mixer/src/Chain.C deleted file mode 100644 index d0b173a..0000000 --- a/mixer/src/Chain.C +++ /dev/null @@ -1,991 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Filter chain. This would all be much simpler if we chose not to - * allow non 1:1 plugins to be mixed in a single chain... - * - * Supporting the mixture requires duplicating some inputs (to satisfy - * stereo input plugins reading mono outputs) and duplicating some - * plugins (to satisfy mono input plugins reading stereo outputs). - * - * Basically, what this means is that the intermediate number of - * buffers need not have any relation to the starting and ending - * buffer count. (Picture an ambisonic panner going into an ambisonic - * decoder (1:6:2). - * - * The chain will allocate enough buffers to hold data from the - * maximum number of channels used by a contained module. - * - * The process thread goes as follows: - * - * 1. Copy inputs to chain buffers. - * - * 2. process() each module in turn (reusing buffers in-place) (inputs - * will be copied or plugins duplicated as necessary) - * - * 3. Copy chain buffers to outputs. - * - * For chains where the number of channels never exceeds the maximum - * of the number of inputs and outputs, the first copy can be - * optimized out. - */ - -#include "const.h" -#include -#include -#include - -#include "Chain.H" -#include "Module.H" -#include "Meter_Module.H" -#include "JACK_Module.H" -#include "Gain_Module.H" -#include "Plugin_Module.H" -#include "Controller_Module.H" - -#include -#include -#include -#include -#include -#include "FL/Fl_Flowpack.H" -#include "FL/Fl_Scroll.H" -#include "FL/Fl_Packscroller.H" -#include -#include "FL/menu_popup.H" -#include "FL/test_press.H" - -#include "debug.h" -#include "Group.H" - -#include "Mixer_Strip.H" -#include -#include "Mixer.H" -extern char *instance_name; - - - -/* Chain::Chain ( int X, int Y, int W, int H, const char *L ) : */ -/* Fl_Group( X, Y, W, H, L) */ -Chain::Chain ( ) : Fl_Group( 0, 0, 100, 100, "") - -{ - /* not really deleting here, but reusing this variable */ - _deleting = true; - - int X = 0; - int Y = 0; - int W = 100; - int H = 100; - -/* _outs = 1; */ -/* _ins = 1; */ - - _configure_outputs_callback = NULL; - - _strip = NULL; - - _name = NULL; - - labelsize( 10 ); - align( FL_ALIGN_TOP ); - - { Fl_Flip_Button* o = tab_button = new Fl_Flip_Button( X, Y, W, 16, "chain/controls"); - o->type(1); - o->labelsize( 12 ); - o->callback( cb_handle, this ); - } - - Y += 18; - H -= 18; - - { Fl_Group *o = chain_tab = new Fl_Group( X, Y, W, H, "" ); - o->labeltype( FL_NO_LABEL ); - o->box( FL_FLAT_BOX ); -// o->color( fl_darker( FL_BACKGROUND_COLOR ) ); -// o->color( FL_BACKGROUND_COLOR ); -// o->box( FL_NO_BOX ); - { Fl_Packscroller *o = new Fl_Packscroller( X, Y, W, H ); - o->color( FL_BACKGROUND_COLOR ); -// o->box( FL_FLAT_BOX ); - o->box( FL_THIN_UP_BOX ); - o->type( Fl_Scroll::VERTICAL ); - { Fl_Pack *o = modules_pack = new Fl_Pack( X, Y, W, H ); - o->type( Fl_Pack::VERTICAL ); - o->spacing( 6 ); - o->end(); - Fl_Group::current()->resizable( o ); - } - o->end(); - } - o->end(); - } - { Fl_Group *o = control_tab = new Fl_Group( X, Y, W, H, "" ); - o->box( FL_FLAT_BOX ); - o->color( FL_BACKGROUND_COLOR ); - o->labeltype( FL_NO_LABEL ); - o->hide(); - { Fl_Scroll *o = new Fl_Scroll( X, Y, W, H ); - o->color( FL_BACKGROUND_COLOR ); - o->box( FL_NO_BOX ); - o->type( Fl_Scroll::VERTICAL ); - { Fl_Pack *o = controls_pack = new Fl_Pack( X, Y, W, H ); - o->type( Fl_Pack::VERTICAL ); - o->spacing( 5 ); -// o->color( FL_RED ); - o->end(); - Fl_Group::current()->resizable( o ); - } - o->end(); - Fl_Group::current()->resizable( o ); - } - o->end(); - o->hide(); - Fl_Group::current()->resizable( o ); - } - end(); - - log_create(); - - _deleting = false; -} - -Chain::~Chain ( ) -{ - DMESSAGE( "Destroying chain" ); - - log_destroy(); - - _deleting = true; - - client()->lock(); - - for ( unsigned int i = scratch_port.size(); i--; ) - free( (sample_t*)scratch_port[i].buffer() ); - - /* if we leave this up to FLTK, it will happen after we've - already destroyed the client */ - modules_pack->clear(); - controls_pack->clear(); - - client()->unlock(); -} - -Group * -Chain::client ( void ) -{ - return strip()->group(); -} - - - -void -Chain::get ( Log_Entry &e ) const -{ - e.add( ":strip", strip() ); - e.add( ":tab", tab_button->value() ? "controls" : "chain" ); -} - -void -Chain::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":tab" ) ) - { - tab_button->value( strcmp( v, "controls" ) == 0 ); - tab_button->do_callback(); - } - else if ( ! strcmp( s, ":strip" ) ) - { - int i; - sscanf( v, "%X", &i ); - Mixer_Strip *t = (Mixer_Strip*)Loggable::find( i ); - - assert( t ); - - t->chain( this ); - } - } -} - - - -void -Chain::log_children ( void ) const -{ - log_create(); - - for ( int i = 0; i < modules(); ++i ) - { - module(i)->log_create(); - } - - for ( int i = 0; i < controls_pack->children(); ++i ) - { - Controller_Module *cm = (Controller_Module*)controls_pack->child( i ); - - cm->log_create(); - } -} - -/* Fill this chain with JACK I/O, Gain, and Meter modules. */ -void -Chain::initialize_with_default ( void ) -{ - - { JACK_Module *m = new JACK_Module(); - m->is_default( true ); - m->chain( this ); - m->configure_outputs( 1 ); - add( m ); - } - - { Module *m = new Gain_Module(); - m->is_default( true ); - m->chain(this); - add( m ); - } - - { Module *m = new Meter_Module(); - m->is_default( true ); - add( m ); - } - - { JACK_Module *m = new JACK_Module(); - m->is_default( true ); - m->chain( this ); - add( m ); - } -} - - -void Chain::cb_handle(Fl_Widget* o) { - if ( o == tab_button ) - { - Fl_Flip_Button *fb = (Fl_Flip_Button*)o; - - if ( fb->value() == 0 ) - { - control_tab->hide(); - chain_tab->show(); - } - else - { - chain_tab->hide(); - control_tab->show(); - } - } -} - -void Chain::cb_handle(Fl_Widget* o, void* v) { - ((Chain*)(v))->cb_handle(o); -} - -void -Chain::remove ( Controller_Module *m ) -{ - DMESSAGE( "Removing controller module from chain" ); - - client()->lock(); - - m->disconnect(); - - controls_pack->remove( m ); - modules_pack->remove( m ); - - build_process_queue(); - - client()->unlock(); - - redraw(); -} - -void -Chain::send_feedback ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - module(i)->send_feedback(); -} - -/* remove a module from the chain. this isn't guaranteed to succeed, - * because removing the module might result in an invalid routing */ -void -Chain::remove ( Module *m ) -{ - int i = modules_pack->find( m ); - - int ins = 0; - - if ( i != 0 ) - ins = module( i - 1 )->noutputs(); - - if ( ! can_configure_outputs( m, ins ) ) - { - fl_alert( "Can't remove module at this point because the resultant chain is invalid" ); - } - - client()->lock(); - - strip()->handle_module_removed( m ); - - modules_pack->remove( m ); - - configure_ports(); - - client()->unlock(); -} - -/* determine number of output ports, signal if changed. */ -void -Chain::configure_ports ( void ) -{ - int nouts = 0; - - client()->lock(); - - for ( int i = 0; i < modules(); ++i ) - { - module( i )->configure_inputs( nouts ); - nouts = module( i )->noutputs(); - } - - unsigned int req_buffers = required_buffers(); - - DMESSAGE( "required_buffers = %i", req_buffers ); - - if ( scratch_port.size() < req_buffers ) - { - for ( unsigned int i = scratch_port.size(); i--; ) - free(scratch_port[i].buffer()); - scratch_port.clear(); - - for ( unsigned int i = 0; i < req_buffers; ++i ) - { - Module::Port p( NULL, Module::Port::OUTPUT, Module::Port::AUDIO ); - p.set_buffer( buffer_alloc( client()->nframes() ) ); - buffer_fill_with_silence( (sample_t*)p.buffer(), client()->nframes() ); - scratch_port.push_back( p ); - } - } - - build_process_queue(); - - client()->unlock(); - - parent()->redraw(); -} - -/** invoked from the JACK latency callback... We need to update the latency values on this chains ports */ -void -Chain::set_latency ( JACK::Port::direction_e dir ) -{ - nframes_t tmax = 0; - nframes_t tmin = 0; - nframes_t added_min = 0; - nframes_t added_max = 0; - - for ( int i = 0; i < modules(); i++ ) - { - Module *m; - - if ( dir == JACK::Port::Input ) - m = module( i ); - else - m = module( (modules() - 1) - i ); - - nframes_t min,max; - min = max = 0; - - nframes_t a = m->get_module_latency(); - - added_min += a; - added_max += a; - - if ( dir == JACK::Port::Input ? m->aux_audio_input.size() : m->aux_audio_output.size() ) - { - m->get_latency( dir, &min, &max ); - - tmin = 0; - added_min = 0; - } - - if ( min > tmin ) - tmin = min; - if ( max > tmax ) - tmax = max; - - m->set_latency( dir, tmin + added_min, tmax + added_max ); - - } -} - -int -Chain::get_module_instance_number ( Module *m ) -{ - int n = 0; - - for ( int i = 0; i < modules() && module(i) != m; ++i ) - if ( ! strcmp( module(i)->label(), m->label() ) ) - n++; - - return n; -} - -/* calculate the minimum number of buffers required to satisfy this chain */ -int -Chain::required_buffers ( void ) -{ - int buffers = 0; - int outs = 0; - - for ( int i = 0; i < modules(); ++i ) - { - outs = module( i )->can_support_inputs( outs ); - - if ( outs > buffers ) - buffers = outs; - } - - return buffers; -} - -/* called by a module when it wants to alter the number of its - * outputs. Also used to test for chain validity when inserting / - * removing modules */ -bool -Chain::can_configure_outputs ( Module *m, int n ) const -{ - /* start at the requesting module */ - - int outs = n; - - int i = modules_pack->find( m ); - - if ( modules() - 1 == i ) - /* last module */ - return true; - - for ( i++ ; i < modules(); ++i ) - { - outs = module( i )->can_support_inputs( outs ); - - if ( outs < 0 ) - return false; - } - - return true; -} - -unsigned int -Chain::maximum_name_length ( void ) -{ - return JACK::Client::maximum_name_length() - ( strlen( instance_name ) + 1 ); -} - -void -Chain::freeze_ports ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - { - Module *m = module(i); - m->freeze_ports(); - } -} - -void -Chain::thaw_ports ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - { - Module *m = module(i); - m->thaw_ports(); - } -} - -/* rename chain... we have to let our modules know our name has - * changed so they can take the appropriate action (in particular the - * JACK module). */ -void -Chain::name ( const char *name ) -{ - _name = name; - - if ( strip()->group() ) - { - if ( strip()->group()->single() ) - strip()->group()->name(name); - } - - for ( int i = 0; i < modules(); ++i ) - { - module( i )->handle_chain_name_changed(); - } -} - -bool -Chain::add ( Module *m ) -{ - /* FIXME: hacky */ - if ( !strcmp( m->name(), "Controller" ) ) - return false; - else - return insert( NULL, m ); -} - -bool -Chain::add ( Controller_Module *m ) -{ - DMESSAGE( "Adding control" ); - add_control(m); - return true; -} - -bool -Chain::insert ( Module *m, Module *n ) -{ - client()->lock(); - - if ( !m ) - { - if ( modules() == 0 && n->can_support_inputs( 0 ) >= 0 ) - { - n->chain( this ); - n->configure_inputs( 0 ); - modules_pack->add( n ); - } - else if ( n->can_support_inputs( module( modules() - 1 )->noutputs() ) >= 0 ) - { - n->chain( this ); - n->configure_inputs( module( modules() - 1 )->noutputs() ); - modules_pack->add( n ); - } - else - { - DMESSAGE( "Module says it can't support %i inputs", module( modules() - 1 )->noutputs() ); - - goto err; - } - } - else - { - int i = modules_pack->find( m ); - - n->chain( this ); - - if ( 0 == i ) - { - /* inserting to head of chain*/ - if ( n->can_support_inputs( 0 ) >= 0 ) - n->configure_inputs( 0 ); - else - goto err; - } - else - { - if ( n->can_support_inputs( module( i - 1 )->noutputs() ) >= 0 ) - { - n->configure_inputs( module( i - 1 )->noutputs() ); - - m->configure_inputs( n->noutputs() ); - - for ( int j = i + 1; j < modules(); ++j ) - module( j )->configure_inputs( module( j - 1 )->noutputs() ); - } - else - goto err; - } - - modules_pack->insert( *n, i ); - } - - - strip()->handle_module_added( n ); - - configure_ports(); - - client()->unlock(); - - DMESSAGE( "Module \"%s\" has %i:%i audio and %i:%i control ports", - n->name(), - n->ninputs(), - n->noutputs(), - n->ncontrol_inputs(), - n->ncontrol_outputs() ); - - n->initialize(); - return true; - -err: - - client()->unlock(); - - DMESSAGE( "Insert failed" ); - - return false; -} - -/* add a control to the control strip. Assumed to already be connected! */ -void -Chain::add_control ( Controller_Module *m ) -{ - client()->lock(); - - controls_pack->add( m ); - - configure_ports(); - - client()->unlock(); - - controls_pack->redraw(); -} - -void -Chain::draw_connections ( Module *m ) -{ - int spacing; - int offset; - - int X, Y, W, H; - - ((Fl_Packscroller*)chain_tab->child( 0 ))->bbox( X, Y, W, H ); - - fl_push_clip( X, Y, W, H ); - - Fl_Color c = FL_FOREGROUND_COLOR; - fl_color( c ); - - if ( m->ninputs() ) - { - spacing = w() / m->ninputs(); - offset = spacing / 2; - - for ( int i = m->ninputs(); i--; ) - fl_rectf( m->x() + offset + ( spacing * i ), m->y() - 3, 2, 3 ); - } - - fl_color( fl_darker( c ) ); - - if ( m->noutputs() ) - { - spacing = w() / m->noutputs(); - offset = spacing / 2; - for ( int i = m->noutputs(); i--; ) - fl_rectf( m->x() + offset + ( spacing * i ), m->y() + m->h(), 2, 3 ); - } - - fl_pop_clip(); -} - -void -Chain::add_to_process_queue ( Module *m ) -{ - for ( std::list::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) - if ( m == *i ) - return; - - process_queue.push_back( m ); -} - -/* run any time the internal connection graph might have - * changed... Tells the process thread what order modules need to be - * run in. */ -void -Chain::build_process_queue ( void ) -{ - process_queue.clear(); - - for ( int i = 0; i < modules(); ++i ) - { - Module *m = (Module*)module( i ); - - /* controllers */ - for ( unsigned int j = 0; j < m->control_input.size(); ++j ) - { - if ( m->control_input[j].connected() ) - { - add_to_process_queue( m->control_input[j].connected_port()->module() ); - } - } - - /* audio modules */ - add_to_process_queue( m ); - - /* indicators */ - for ( unsigned int j = 0; j < m->control_output.size(); ++j ) - { - if ( m->control_output[j].connected() ) - { - add_to_process_queue( m->control_output[j].connected_port()->module() ); - } - } - } - - /* connect all the ports to the buffers */ - for ( int i = 0; i < modules(); ++i ) - { - - Module *m = module( i ); - - for ( unsigned int j = 0; j < m->audio_input.size(); ++j ) - { - m->audio_input[j].set_buffer( scratch_port[j].buffer() ); - } - for ( unsigned int j = 0; j < m->audio_output.size(); ++j ) - { - m->audio_output[j].set_buffer( scratch_port[j].buffer() ); - } - - m->handle_port_connection_change(); - } - -/* DMESSAGE( "Process queue looks like:" ); */ - -/* for ( std::list::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) */ -/* { */ -/* const Module* m = *i; */ - -/* if ( m->audio_input.size() || m->audio_output.size() ) */ -/* DMESSAGE( "\t%s", (*i)->name() ); */ -/* else if ( m->control_output.size() ) */ -/* DMESSAGE( "\t%s -->", (*i)->name() ); */ -/* else if ( m->control_input.size() ) */ -/* DMESSAGE( "\t%s <--", (*i)->name() ); */ - -/* { */ -/* char *s = m->get_parameters(); */ - -/* DMESSAGE( "(%s)", s ); */ - -/* delete[] s; */ -/* } */ -/* } */ -} - -void -Chain::strip ( Mixer_Strip * ms ) -{ - _strip = ms; -} - - - -void -Chain::draw ( void ) -{ - Fl_Group::draw(); - -/* if ( 0 == strcmp( "Chain", tabs->value()->label() ) ) */ - if ( chain_tab->visible() ) - for ( int i = 0; i < modules(); ++i ) - draw_connections( module( i ) ); -} - -void -Chain::resize ( int X, int Y, int W, int H ) -{ - Fl_Group::resize( X, Y, W, H ); - -/* this won't naturally resize because it's inside of an Fl_Scroll... */ - controls_pack->size( W, controls_pack->h() ); -} - -void -Chain::get_output_ports ( std::list &sl) -{ - for ( int i = 0; i < modules(); i++ ) - { - Module *m = module(i); - - for ( unsigned int j = 0; j < m->aux_audio_output.size(); j++ ) - { - char *s; - - asprintf( &s, "%s/%s", - "*", - m->aux_audio_output[j].jack_port()->name() ); - - sl.push_back( s ); - - free(s); - - if ( ! strip()->group()->single() ) - { - asprintf( &s, "%s/%s", - strip()->group()->name(), - m->aux_audio_output[j].jack_port()->name() ); - - - sl.push_back( s ); - - free(s); - } - } - } -} - -void -Chain::auto_connect_outputs ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - { - module(i)->auto_connect_outputs(); - } -} - -void -Chain::auto_disconnect_outputs ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - { - module(i)->auto_disconnect_outputs(); - } -} - - - - -/*****************/ -/* Import/Export */ -/*****************/ - -void -Chain::snapshot ( void *v ) -{ - ((Chain*)v)->snapshot(); -} - -void -Chain::snapshot ( void ) -{ - log_children(); -} - -bool -Chain::do_export ( const char *filename ) -{ - MESSAGE( "Exporting chain state" ); - Loggable::snapshot_callback( &Chain::snapshot, this ); - Loggable::snapshot( filename ); - return true; -} - - - -/**********/ -/* Client */ -/**********/ - -void -Chain::process ( nframes_t nframes ) -{ - for ( std::list::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i ) - { - Module *m = *i; - - m->process( nframes ); - } -} - -void -Chain::buffer_size ( nframes_t nframes ) -{ - for ( unsigned int i = scratch_port.size(); i--; ) - free(scratch_port[i].buffer()); - scratch_port.clear(); - - configure_ports(); - - for ( int i = 0; i < modules(); ++i ) - { - Module *m = module(i); - - m->resize_buffers( nframes ); - } -} - -int -Chain::sample_rate_change ( nframes_t nframes ) -{ - Module::set_sample_rate ( nframes ); - for ( int i = 0; i < modules(); ++i ) - { - Module *m = module(i); - - m->handle_sample_rate_change( nframes ); - } - - return 0; -} - -/* handle jack port connection change */ -void -Chain::port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ) -{ - if ( _deleting ) - return; - - /* this is called from JACK non-RT thread... */ - - if ( jack_port_is_mine( client()->jack_client(), jack_port_by_id( client()->jack_client(), a ) ) || - jack_port_is_mine( client()->jack_client(), jack_port_by_id( client()->jack_client(), b ) )) - { - Fl::awake( Chain::update_connection_status, this ); - } -} - -void -Chain::update ( void ) -{ - for ( int i = 0; i < controls_pack->children(); ++i ) - { - Controller_Module *cm = (Controller_Module*)controls_pack->child( i ); - cm->update(); - } - - for ( int i = 0; i < modules(); i++ ) - { - Module *m = module(i); - m->update(); - } -} - -void -Chain::update_connection_status ( void *v ) -{ - ((Chain*)v)->update_connection_status(); -} - -void -Chain::update_connection_status ( void ) -{ - for ( int i = 0; i < modules(); i++ ) - { - Module *m = module(i); - - if ( !strcmp( m->basename(), "JACK" ) ) - { - ((JACK_Module*)m)->update_connection_status(); - } - } -} diff --git a/mixer/src/Chain.H b/mixer/src/Chain.H deleted file mode 100644 index c11cdad..0000000 --- a/mixer/src/Chain.H +++ /dev/null @@ -1,149 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include -#include - -#include "Module.H" -#include "JACK/Port.H" -#include -#include -#include "Loggable.H" -#include "Group.H" - -class Mixer_Strip; -class Fl_Flowpack; -class Fl_Flip_Button; -class Controller_Module; - -class Chain : public Fl_Group, public Loggable { - - Fl_Flip_Button *tab_button; - Fl_Pack *controls_pack; - Fl_Group *chain_tab; - Fl_Group *control_tab; - Fl_Pack *modules_pack; - - Mixer_Strip *_strip; - const char *_name; - - std::list process_queue; - - std::vector scratch_port; - - Fl_Callback *_configure_outputs_callback; - void *_configure_outputs_userdata; - - bool _deleting; - -private: - - static void snapshot ( void *v ); - void snapshot ( void ); - - void cb_handle(Fl_Widget*); - static void cb_handle(Fl_Widget*, void*); - - void draw_connections ( Module *m ); - void build_process_queue ( void ); - void add_to_process_queue ( Module *m ); - - static void update_connection_status ( void *v ); - void update_connection_status ( void ); - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - -public: - - void auto_connect_outputs ( void ); - void auto_disconnect_outputs ( void ); - - void get_output_ports ( std::list &sl); - - void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ); - void buffer_size ( nframes_t nframes ); - int sample_rate_change ( nframes_t nframes ); - void process ( nframes_t ); - - Chain ( int X, int Y, int W, int H, const char *L = 0 ); - Chain ( ); - virtual ~Chain ( ); - - void update ( void ); - void draw ( void ); - void resize ( int X, int Y, int W, int H ); - - Mixer_Strip *strip ( void ) const { return _strip; } - void strip ( Mixer_Strip *v ); - const char *name ( void ) const { return _name; } - void name ( const char *name ); - - void send_feedback ( void ); - - int get_module_instance_number ( Module *m ); - - void configure_ports ( void ); - int required_buffers ( void ); - - bool can_support_input_channels ( int n ); - - int modules ( void ) const { return modules_pack->children(); } - Module *module ( int n ) const { return (Module*)modules_pack->child( n ); } - void remove ( Controller_Module *m ); - void remove ( Module *m ); - bool add ( Module *m ); - bool add ( Controller_Module *m ); - bool insert ( Module *m, Module *n ); - void add_control ( Controller_Module *m ); - - bool do_export ( const char *filename ); - - void initialize_with_default ( void ); - - bool can_configure_outputs ( Module *m, int n ) const; - - void configure_outputs_callback ( Fl_Callback *cb, void *v ) - { - _configure_outputs_callback = cb; - _configure_outputs_userdata = v; - } - - void set_latency ( JACK::Port::direction_e ); - - Fl_Callback * configure_outputs_callback ( void ) const { return _configure_outputs_callback; } - - virtual void log_children ( void ) const; - - static unsigned int maximum_name_length ( void ); - - Group *client ( void ); - - void freeze_ports ( void ); - void thaw_ports ( void ); - -// void client ( Client * ); - - LOG_CREATE_FUNC( Chain ); -}; diff --git a/mixer/src/Controller_Module.C b/mixer/src/Controller_Module.C deleted file mode 100644 index 74eaca9..0000000 --- a/mixer/src/Controller_Module.C +++ /dev/null @@ -1,994 +0,0 @@ -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" - -#include "Controller_Module.H" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "FL/Fl_DialX.H" -#include "FL/Fl_Labelpad_Group.H" -#include "FL/Fl_Value_SliderX.H" -#include "Panner.H" -#include "FL/test_press.H" -#include "FL/menu_popup.H" - -#include "Chain.H" -#include "OSC/Endpoint.H" - -// needed for mixer->endpoint -#include "Mixer.H" -#include "Spatialization_Console.H" -#include "string_util.h" - - - -bool Controller_Module::learn_by_number = false; -bool Controller_Module::_learn_mode = false; - - -void -Controller_Module::take_focus ( void ) -{ - bool v = visible_focus(); - - if ( ! v ) - set_visible_focus(); - - Fl_Widget::take_focus(); - - if ( ! v ) - clear_visible_focus(); -} - -Controller_Module::Controller_Module ( bool is_default ) : Module( is_default, 50, 100, name() ) -{ -// label( "" ); - box( FL_NO_BOX ); - - _horizontal = true; - _pad = true; - control = 0; - control_value =0.0f; - - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - - _mode = GUI; - -// mode( GUI ); -// mode( CV ); -// configure_inputs( 1 ); - - end(); - -// clear_visible_focus(); - log_create(); -} - -Controller_Module::~Controller_Module ( ) -{ - log_destroy(); - - /* shutdown JACK port, if we have one */ - mode( GUI ); - -// disconnect(); -} - -void -Controller_Module::handle_chain_name_changed() -{ - if ( type() == SPATIALIZATION ) - { - if ( Mixer::spatialization_console ) - Mixer::spatialization_console->update(); - } - -// change_osc_path( generate_osc_path() ); -} - -void -Controller_Module::handle_control_disconnect ( Module::Port *p ) -{ - if ( type() == SPATIALIZATION ) - { - if ( Mixer::spatialization_console ) - Mixer::spatialization_console->update(); - } -} - -void -Controller_Module::disconnect ( void ) -{ - for ( unsigned int i = 0; i < control_output.size(); ++i ) - control_output[i].disconnect(); -} - - - -void -Controller_Module::get ( Log_Entry &e ) const -{ - Module::get( e ); - - Port *p = control_output[0].connected_port(); - - if ( !p ) - { - e.add( ":module", "" ); - e.add( ":port", "" ); - e.add( ":mode", "" ); - } - else - { - Module *m = p->module(); - - e.add( ":module", m ); - e.add( ":port", m->control_input_port_index( p ) ); - e.add( ":mode", mode() ); - } -} - -void -Controller_Module::set ( Log_Entry &e ) -{ - Module::set( e ); - - int port = -1; - Module *module = NULL; - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":port" ) ) - { - port = atoi( v ); - } - else if ( ! strcmp( s, ":module" ) ) - { - int i; - sscanf( v, "%X", &i ); - Module *t = (Module*)Loggable::find( i ); - - assert( t ); - - module = t; - } - } - - if ( port >= 0 && module ) - { - connect_to( &module->control_input[port] ); - module->chain()->add_control( this ); - label( module->control_input[port].name() ); - } - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":mode" ) ) - { - mode( (Mode)atoi( v ) ); - } - } - -} - - - -void -Controller_Module::mode ( Mode m ) -{ - if( mode() != CV && m == CV ) - { - if ( control_output[0].connected() ) - { - chain()->client()->lock(); - - Port *p = control_output[0].connected_port(); - - char prefix[512]; - snprintf( prefix, sizeof(prefix), "CV-%s", p->name() ); - - add_aux_cv_input( prefix, 0 ); - - chain()->client()->unlock(); - } - } - else if ( mode() == CV && m != CV ) - { - chain()->client()->lock(); - - aux_audio_input.back().jack_port()->shutdown(); - - delete aux_audio_input.back().jack_port(); - - aux_audio_input.pop_back(); - - chain()->client()->unlock(); - } - - _mode = m ; -} - - -bool -Controller_Module::connect_spatializer_radius_to ( Module *m ) -{ - Port *radius_port = NULL; - float radius_value = 0.0f; - - for ( unsigned int i = 0; i < m->control_input.size(); ++i ) - { - Port *p = &m->control_input[i]; - - if ( !strcasecmp( "Radius", p->name() ) ) - /* 90.0f == p->hints.maximum && */ - /* -90.0f == p->hints.minimum ) */ - { - radius_port = p; - radius_value = p->control_value(); - continue; - } - } - - if ( ! radius_port ) - return false; - - if ( control_output.size() != 3 ) - { - control_output.clear(); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - } - - - control_output[2].connect_to( radius_port ); - - maybe_create_panner(); - - Panner *o = (Panner*)control; - - o->point( 0 )->radius( radius_value ); - - if ( Mixer::spatialization_console ) - Mixer::spatialization_console->update(); - - return true; -} - -void -Controller_Module::maybe_create_panner ( void ) -{ - if ( _type != SPATIALIZATION ) - { - clear(); - - Panner *o = new Panner( 0,0, 92,92 ); - - o->box(FL_FLAT_BOX); - o->color(FL_GRAY0); - o->selection_color(FL_BACKGROUND_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(FL_ALIGN_TOP); - o->when(FL_WHEN_CHANGED); - label( "Spatialization" ); - - o->align(FL_ALIGN_TOP); - o->labelsize( 10 ); -// o->callback( cb_panner_value_handle, new callback_data( this, azimuth_port_number, elevation_port_number ) ); - - - o->callback( cb_spatializer_handle, this ); - - control = (Fl_Valuator*)o; - - if ( _pad ) - { - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( o ); - flg->position( x(), y() ); - flg->set_visible_focus(); - size( flg->w(), flg->h() ); - add( flg ); - } - else - { -// o->clear_visible_focus(); - o->resize( x(), y(), w(), h() ); - add( o ); - resizable( o ); - init_sizes(); - } - - _type = SPATIALIZATION; - } -} - -/** attempt to transform this controller into a spatialization - controller and connect to the given module's spatialization - control inputs. Returns true on success, false if given module - does not accept spatialization inputs. */ -bool -Controller_Module::connect_spatializer_to ( Module *m ) -{ - connect_spatializer_radius_to( m ); - - /* these are for detecting related parameter groups which can be - better represented by a single control */ - Port *azimuth_port = NULL; - float azimuth_value = 0.0f; - Port *elevation_port = NULL; - float elevation_value = 0.0f; - - for ( unsigned int i = 0; i < m->control_input.size(); ++i ) - { - Port *p = &m->control_input[i]; - - if ( !strcasecmp( "Azimuth", p->name() ) && - 180.0f == p->hints.maximum && - -180.0f == p->hints.minimum ) - { - azimuth_port = p; - azimuth_value = p->control_value(); - continue; - } - else if ( !strcasecmp( "Elevation", p->name() ) && - 90.0f == p->hints.maximum && - -90.0f == p->hints.minimum ) - { - elevation_port = p; - elevation_value = p->control_value(); - continue; - } - } - - if ( ! ( azimuth_port && elevation_port ) ) - return false; - - if ( control_output.size() != 3 ) - { - control_output.clear(); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - add_port( Port( this, Port::OUTPUT, Port::CONTROL ) ); - } - - control_output[0].connect_to( azimuth_port ); - control_output[1].connect_to( elevation_port ); - - maybe_create_panner(); - - Panner *o = (Panner*)control; - - o->point( 0 )->azimuth( azimuth_value ); - o->point( 0 )->elevation( elevation_value ); - - if ( Mixer::spatialization_console ) - Mixer::spatialization_console->update(); - - return true; -} - -void -Controller_Module::connect_to ( Port *p ) -{ - control_output[0].connect_to( p ); - - clear(); - - Fl_Widget *w; - - if ( p->hints.type == Module::Port::Hints::BOOLEAN ) - { - Fl_Button *o = new Fl_Button( 0, 0, 40, 40, p->name() ); - w = o; - o->type( FL_TOGGLE_BUTTON ); - o->value( p->control_value() ); - o->selection_color( fl_color_average( FL_GRAY, FL_CYAN, 0.5 ) ); - - _type = TOGGLE; - - /* FIXME: hack */ - control = (Fl_Valuator*)o; - } - else if ( p->hints.type == Module::Port::Hints::INTEGER ) - { - - Fl_Counter *o = new Fl_Counter(0, 0, 58, 24, p->name() ); - control = o; - w = o; - - o->type(1); - o->step(1); - - if ( p->hints.ranged ) - { - o->minimum( p->hints.minimum ); - o->maximum( p->hints.maximum ); - } - - _type = SPINNER; - - o->value( p->control_value() ); - } - // else if ( p->hints.type == Module::Port::Hints::LOGARITHMIC ) - else - { - Fl_Value_SliderX *o = new Fl_Value_SliderX(0, 0, 30, 250, p->name() ); - control = o; - w = o; - - if ( ! _horizontal ) - { - o->size( 30, 250 ); - o->type(FL_VERT_NICE_SLIDER); - } - else - { - o->size(250,20); - o->type(FL_HOR_NICE_SLIDER); - } - -// o->type(4); - o->color( FL_BACKGROUND2_COLOR ); - o->selection_color( fl_color_average( FL_GRAY, FL_CYAN, 0.5 ) ); - o->minimum(1.5); - o->maximum(0); - o->value(1); -// o->textsize(9); - - if ( p->hints.ranged ) - { - if ( ! _horizontal ) - { - o->minimum( p->hints.maximum ); - o->maximum( p->hints.minimum ); - } - else - { - o->minimum( p->hints.minimum ); - o->maximum( p->hints.maximum ); - } - } - - o->precision(2); - - o->value( p->control_value() ); - - _type = SLIDER; - } - /* else */ - /* { */ - /* { Fl_DialX *o = new Fl_DialX( 0, 0, 50, 50, p->name() ); */ - /* w = o; */ - /* control = o; */ - - /* if ( p->hints.ranged ) */ - /* { */ - /* DMESSAGE( "Min: %f, max: %f", p->hints.minimum, p->hints.maximum ); */ - /* o->minimum( p->hints.minimum ); */ - /* o->maximum( p->hints.maximum ); */ - /* } */ - - /* o->color( fl_darker( FL_GRAY ) ); */ - /* o->selection_color( FL_WHITE ); */ - /* o->value( p->control_value() ); */ - /* } */ - - /* _type = KNOB; */ - /* } */ - - control_value = p->control_value(); - - w->clear_visible_focus(); - w->align(FL_ALIGN_TOP); - w->labelsize( 10 ); - w->callback( cb_handle, this ); - - if ( _pad ) - { - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( w ); - flg->set_visible_focus(); - size( flg->w(), flg->h() ); - flg->position( x(), y() ); - add( flg ); - resizable(flg); -// init_sizes(); - } - else - { - /* HACK: hide label */ - if ( _type == TOGGLE ) - { - w->align( FL_ALIGN_INSIDE ); - } - else - { - w->labeltype( FL_NO_LABEL ); - } - w->resize( x(), y(), this->w(), h() ); - add( w ); - resizable( w ); - init_sizes(); - } -} - -void -Controller_Module::update ( void ) -{ - /* we only need this in CV (JACK) mode, because with other forms - * of control the change happens in the GUI thread and we know it */ - if ( mode() != CV ) - return; - - /* ensures that port value change callbacks are run */ - if ( control && control_output.size() > 0 && control_output[0].connected() ) - control_output[0].connected_port()->control_value( control_value ); -} - -void -Controller_Module::cb_handle ( Fl_Widget *w, void *v ) -{ - ((Controller_Module*)v)->cb_handle( w ); -} - -void -Controller_Module::cb_handle ( Fl_Widget *w ) -{ - if ( type() == TOGGLE ) - { - control_value = ((Fl_Button*)w)->value(); - } - else - control_value = ((Fl_Valuator*)w)->value(); - - if ( control_output[0].connected() ) - control_output[0].connected_port()->control_value( control_value ); -} - - -void -Controller_Module::cb_spatializer_handle ( Fl_Widget *w, void *v ) -{ - ((Controller_Module*)v)->cb_spatializer_handle( w ); -} - -void -Controller_Module::cb_spatializer_handle ( Fl_Widget *w ) -{ - Panner *pan = (Panner*)w; - - if ( control_output[0].connected() && - control_output[1].connected() ) - { - control_output[0].connected_port()->control_value( pan->point( 0 )->azimuth() ); - control_output[1].connected_port()->control_value( pan->point( 0 )->elevation() ); - } - - if ( control_output[2].connected() ) - { - control_output[2].connected_port()->control_value( pan->point( 0 )->radius() ); - } -} - -void -Controller_Module::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Controller_Module*)v)->menu_cb( (Fl_Menu_*) w ); -} - -void -Controller_Module::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[256]; - - m->item_pathname( picked, sizeof( picked ) ); - - Logger log( this ); - - if ( ! strcmp( picked, "Mode/GUI + OSC" ) ) - mode( GUI ); - else if ( ! strcmp( picked, "Mode/Control Voltage (JACK)" ) ) - mode( CV ); - else if ( ! strcmp( picked, "/Remove" ) ) - command_remove(); - else if ( ! strncmp( picked, "Connect To/", strlen( "Connect To/" ) ) ) - { - char *peer_name = index( picked, '/' ) + 1; - - *index( peer_name, '/' ) = 0; - -// OSC::Signal s = (OSC::Signal*)m->mvalue()->user_data(); - const char *path = ((OSC::Signal*)m->mvalue()->user_data())->path(); - - /* if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) */ - /* { */ - /* _persistent_osc_connections.push_back( strdup(path) ); */ - - Port *p = control_output[0].connected_port(); - - if ( learn_by_number ) - mixer->osc_endpoint->add_translation( path, p->osc_number_path()); - else - mixer->osc_endpoint->add_translation( path, p->osc_path() ); - } - else if ( ! strncmp( picked, "Disconnect From/", strlen( "Disconnect From/" ) ) ) - { - /* char *peer_name = index( picked, '/' ) + 1; */ - - /* *index( peer_name, '/' ) = 0; */ - -// OSC::Signal s = (OSC::Signal*)m->mvalue()->user_data(); - const char *path = (const char*)m->mvalue()->user_data(); - - /* if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) */ - /* { */ - /* _persistent_osc_connections.push_back( strdup(path) ); */ - - // Port *p = control_output[0].connected_port(); - - mixer->osc_endpoint->del_translation( path ); - - /* if ( learn_by_number ) */ - /* { */ - /* char *our_path = p->osc_number_path(); */ - - /* mixer->osc_endpoint->add_translation( path, our_path ); */ - - /* free(our_path); */ - /* } */ - /* else */ - /* mixer->osc_endpoint->add_translation( path, p->osc_path() ); */ - } - - - - /* } */ - /* else */ - /* { */ - /* /\* timeline->osc->disconnect_signal( _osc_output(), path ); *\/ */ - - /* /\* for ( std::list::iterator i = _persistent_osc_connections.begin(); *\/ */ - /* /\* i != _persistent_osc_connections.end(); *\/ */ - /* /\* ++i ) *\/ */ - /* /\* { *\/ */ - /* /\* if ( !strcmp( *i, path ) ) *\/ */ - /* /\* { *\/ */ - /* /\* free( *i ); *\/ */ - /* /\* i = _persistent_osc_connections.erase( i ); *\/ */ - /* /\* break; *\/ */ - /* /\* } *\/ */ - /* /\* } *\/ */ - - /* //free( path ); */ - /* } */ - - - -} -static Fl_Menu_Button *peer_menu; -static const char *peer_prefix; - -void -Controller_Module::peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ) -{ - char *s; - - DMESSAGE( "Paramter limits: %f %f", sig->parameter_limits().min, sig->parameter_limits().max ); - - /* only show outputs */ - if ( sig->direction() != OSC::Signal::Output ) - return; - - - /* only list CV signals for now */ - if ( ! ( sig->parameter_limits().min == 0.0 && - sig->parameter_limits().max == 1.0 ) ) - return; - - if ( ! v ) - { - /* if( state == OSC::Signal::Created ) */ - /* timeline->connect_osc(); */ - /* else */ - /* timeline->update_osc_connection_state(); */ - } - else - { - /* building menu */ -// const char *name = sig->peer_name(); - - assert( sig->path() ); - - char *path = strdup( sig->path() ); - - unescape_url( path ); - - asprintf( &s, "%s/%s", peer_prefix, path ); - - peer_menu->add( s, 0, NULL, (void*)( sig ), 0 ); - - /* FL_MENU_TOGGLE | */ - /* ( ((Controller_Module*)v)->_osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); */ - - free( path ); - - free( s ); - } -} - -void -Controller_Module::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) -{ - mixer->osc_endpoint->peer_signal_notification_callback( &Controller_Module::peer_callback, NULL ); - - peer_menu = m; - peer_prefix = prefix; - - mixer->osc_endpoint->list_peer_signals( this ); -} - -void -Controller_Module::add_osc_connections_to_menu ( Fl_Menu_Button *m, const char *prefix ) -{ - /* peer_menu = m; */ - const char *peer_prefix = prefix; - -// mixer->osc_endpoint->list_peer_signals( this ); - - Port *p = control_output[0].connected_port(); - - const char *number_path = p->osc_number_path(); - const char *name_path = p->osc_path(); - - const char *paths[] = { number_path,name_path,NULL }; - - for ( const char **cpath = paths; *cpath; cpath++ ) - { - const char ** conn = mixer->osc_endpoint->get_connections( *cpath ); - - if ( conn ) - { - for ( const char **s = conn; *s; s++ ) - { - /* building menu */ - - char *path = strdup( *s ); - - unescape_url( path ); - - char *ns; - asprintf( &ns, "%s/%s", peer_prefix, path ); - - peer_menu->add( ns, 0, NULL, const_cast(*s), 0 ); - - free( path ); -// free(*s); - } - - free( conn ); - } - } -} - -/** build the context menu for this control */ -Fl_Menu_Button & -Controller_Module::menu ( void ) -{ - static Fl_Menu_Button m( 0, 0, 0, 0, "Controller" ); - - m.clear(); - - if ( mode() == GUI ) - { - add_osc_peers_to_menu( &m, "Connect To" ); - add_osc_connections_to_menu( &m, "Disconnect From" ); - } - - m.add( "Mode/GUI + OSC", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 )); - m.add( "Mode/Control Voltage (JACK)", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 )); - m.add( "Remove", 0, 0, 0, is_default() ? FL_MENU_INACTIVE : 0 ); - -// menu_set_callback( m.items(), &Controller_Module::menu_cb, (void*)this ); - m.callback( &Controller_Module::menu_cb, (void*)this ); - // m.copy( items, (void*)this ); - - return m; -} - -void -Controller_Module::draw ( void ) -{ - Fl_Group::draw(); - draw_box(x(),y(),w(),h()); - - if ( learn_mode() ) - { - fl_rectf( x(),y(),w(),h(), fl_color_add_alpha( FL_MAGENTA, 50 ) ); - } -} - -int -Controller_Module::handle ( int m ) -{ - - switch ( m ) - { - case FL_PUSH: - { - if ( learn_mode() ) - { - tooltip( "Now learning control. Move the desired control on your controller" ); - - //connect_to( &module->control_input[port] ); - Port *p = control_output[0].connected_port(); - - if ( p ) - { - const char * path = learn_by_number ? p->osc_number_path() : p->osc_path(); - - DMESSAGE( "Will learn %s", path ); - - mixer->osc_endpoint->learn( path ); - } - - return 1; - } - - if ( Fl::event_button3() ) - { - /* context menu */ - /* if ( type() != SPATIALIZATION ) */ - menu_popup( &menu() ); - - return 1; - } - else - return Fl_Group::handle( m ); - } - } - - return Fl_Group::handle( m ); -} - -void -Controller_Module::handle_control_changed ( Port *p ) -{ - /* ignore changes initiated while mouse is over widget */ - - if ( type() == SPATIALIZATION ) - { - if ( Mixer::spatialization_console ) - Mixer::spatialization_console->handle_control_changed( this ); - } - - if ( contains( Fl::pushed() ) ) - return; - - if ( p ) - control_value = p->control_value(); - - if ( control->value() == control_value ) - return; - - /* if ( control->value() != control_value ) */ - /* { */ - /* redraw(); */ - /* } */ - - if ( type() == SPATIALIZATION ) - { - Panner *pan = (Panner*)control; - - pan->point( 0 )->azimuth( control_output[0].control_value() ); - pan->point( 0 )->elevation( control_output[1].control_value() ); - - if ( control_output[2].connected() ) - { -// Port *pp = control_output[2].connected_port(); - float v = control_output[2].control_value(); -// float s = pp->hints.maximum - pp->hints.minimum; - - pan->point( 0 )->radius( v ); - } - if ( visible_r() ) - pan->redraw(); - } - else - { - if ( type() == TOGGLE ) - ((Fl_Button*)control)->value(control_value); - else - control->value(control_value); - } -} - -void -Controller_Module::command_remove ( void ) -{ - if ( is_default() ) - fl_alert( "Default modules may not be deleted." ); - else - { - chain()->remove( this ); - Fl::delete_widget( this ); - } -} - -/**********/ -/* Client */ -/**********/ - -void -Controller_Module::process ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - if ( type() == SPATIALIZATION ) - { - return; - } - - if ( control_output[0].connected() ) - { - float f = control_value; - - if ( mode() == CV ) - { - f = *((float*)aux_audio_input[0].jack_port()->buffer( nframes )); - - const Port *p = control_output[0].connected_port(); - - if (p->hints.ranged ) - { - // scale value to range. - // we assume that CV values are between 0 and 1 - - float scale = p->hints.maximum - p->hints.minimum; - float offset = p->hints.minimum; - - f = ( f * scale ) + offset; - } - } -// else -// f = *((float*)control_output[0].buffer()); - - *((float*)control_output[0].buffer()) = f; - - control_value = f; - } -} diff --git a/mixer/src/Controller_Module.H b/mixer/src/Controller_Module.H deleted file mode 100644 index 83973ba..0000000 --- a/mixer/src/Controller_Module.H +++ /dev/null @@ -1,127 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" -#include -#include "JACK/Port.H" -#include "OSC/Endpoint.H" - -class Fl_Menu_Button; -class Fl_Menu_; - -class Fl_Valuator; - -class Controller_Module : public Module -{ - - bool _pad; - bool _horizontal; - - volatile float control_value; - - Fl_Menu_Button & menu ( void ); - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( const Fl_Menu_ *m ); - - - static void peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ); - void peer_callback( OSC::Signal *sig, OSC::Signal::State state ); - void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ); - void add_osc_connections_to_menu ( Fl_Menu_Button *m, const char *prefix ); - -public: - - static bool _learn_mode; - - static bool learn_by_number; - static bool learn_mode ( void ) { return _learn_mode; } - static void learn_mode ( bool b ) { _learn_mode = b; } - - enum Mode { GUI, CV, OSC, MIDI }; - - enum Type { KNOB, - SLIDER, - SPINNER, - TOGGLE, - SPATIALIZATION }; - - Mode mode ( void ) const { return _mode; } - void mode ( Mode v ); - - void horizontal ( bool v ) { _horizontal = v; } - Type type ( void ) const { return _type; } - - Controller_Module ( bool is_default = false ); - virtual ~Controller_Module ( ); - - const char *name ( void ) const { return "Controller"; } - - int can_support_inputs ( int ) { return 0; } - bool configure_inputs ( int ) { return false; } - - void pad ( bool v ) { _pad = v; } - - static void cb_handle ( Fl_Widget *w, void *v ); - void cb_handle ( Fl_Widget *w ); - static void cb_spatializer_handle ( Fl_Widget *w, void *v ); - void cb_spatializer_handle ( Fl_Widget *w ); - - void connect_to ( Port *p ); - bool connect_spatializer_to ( Module *m ); - bool connect_spatializer_radius_to ( Module *m ); - void disconnect ( void ); - - void handle_control_changed ( Port *p ); - void handle_chain_name_changed ( void ); - void handle_control_disconnect ( Port *p ); - - virtual void command_remove ( void ); - - LOG_CREATE_FUNC( Controller_Module ); - - virtual void update ( void ); - - void process ( nframes_t nframes ); - - void draw ( void ); - - int handle ( int m ); - - void take_focus ( void ); -// void set_control_value ( float f ) { control_value = f; } - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - -private: - - void maybe_create_panner ( void ); - char *generate_osc_path ( void ); - void change_osc_path ( char *path ); - - Mode _mode; - Type _type; - - Fl_Valuator *control; - -}; diff --git a/mixer/src/DPM.C b/mixer/src/DPM.C deleted file mode 100644 index 35edf23..0000000 --- a/mixer/src/DPM.C +++ /dev/null @@ -1,256 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* a Digital Peak Meter, either horizontal or vertical. Color is a - gradient from min_color() to max_color(). box() is used to draw the - individual 'lights'. division() controls how many 'lights' there - are. value() is volume in dBFS */ - -#include "DPM.H" - -/* we cache the gradient for (probably excessive) speed */ -float DPM::_dim; -Fl_Color DPM::_gradient[128] = { (Fl_Color)0 }; -Fl_Color DPM::_dim_gradient[128]; - -#include -#include -#include - -#include -#include - -DPM::DPM ( int X, int Y, int W, int H, const char *L ) : - Meter( X, Y, W, H, L ) -{ - tooltip( peak_string ); - - _last_drawn_hi_segment = 0; - - pixels_per_segment( 4 ); - - type( FL_VERTICAL ); - -// resize( X, Y, W, H ); - - dim( 0.85f ); - - /* initialize gradients */ - if ( DPM::_gradient[ 0 ] == 0 ) - { - int breaks[] = {0,60,70,80,90,127}; - - Fl_Color cols[] = { - fl_rgb_color( 45,58,64), - fl_rgb_color( 84,181,195 ), - fl_rgb_color( 122,200,211 ), - fl_rgb_color( 178,213,212 ), - fl_rgb_color( 209,213,179 ), - fl_rgb_color( 250, 40, 30 ) - }; - - DPM::blend( 6, breaks, cols ); - } - - box( FL_FLAT_BOX ); - color( FL_BACKGROUND_COLOR ); - - resize( X,Y,W,H); -} - -/* which marks to draw beside meter */ -const int marks [] = { -70, -50, -40, -30, -20, -10, -3, 0, 4 }; - -void -DPM::draw_label ( void ) -{ - - /* dirty hack */ - if ( parent()->child( 0 ) == this ) - { - fl_font( FL_TIMES, 8 ); - fl_color( FL_WHITE ); - /* draw marks */ - char pat[5]; - if ( type() == FL_HORIZONTAL ) - { - for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; ) - { - sprintf( pat, "%d", marks[ i ] ); - - int v = w() * deflection( (float)marks[ i ] ); - - fl_draw( pat, x() + v, (y() + h() + 8), 19, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) ); - } - - } - else - { - for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; ) - { - sprintf( pat, "%d", marks[ i ] ); - - int v = h() * deflection( (float)marks[ i ] ); - - fl_draw( pat, x() - 20, (y() + h() - 4) - v, 19, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) ); - } - } - } -} - -void -DPM::resize ( int X, int Y, int W, int H ) -{ - int old_segments = _segments; - - Fl_Widget::resize( X, Y, W, H ); - - int tx,ty,tw,th; - bbox(tx,ty,tw,th); - - if ( type() == FL_HORIZONTAL ) - _segments = floor( tw / (double)_pixels_per_segment ); - else - _segments = floor( th / (double)_pixels_per_segment ); - - if ( old_segments != _segments ) - _last_drawn_hi_segment = 0; -} - -void DPM::bbox ( int &X, int &Y, int &W, int &H ) -{ - X = x() + 2; - Y = y() + 2; - W = w() - 4; - H = h() - 4; -} - -void -DPM::draw ( void ) -{ - snprintf( peak_string, sizeof( peak_string ), "%.1f", peak() ); - tooltip( peak_string ); - - int X,Y,W,H; - bbox(X,Y,W,H); - - int v = pos( value() ); - int pv = pos( peak() ); - - int clipv = pos( 0 ); - - int bh = H / _segments; - /* int bh = _pixels_per_segment; */ - /* int bw = _pixels_per_segment; */ - int bw = W / _segments; - - if ( damage() & FL_DAMAGE_ALL ) - { - draw_label(); - - draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_DARK1 ); - } - - fl_push_clip( X, Y, W, H ); - - const int active = active_r(); - - int hi, lo; - - /* only draw as many segments as necessary */ - if ( damage() == FL_DAMAGE_USER1 ) - { - if ( v > _last_drawn_hi_segment ) - { - hi = v; - lo = _last_drawn_hi_segment; - } - else - { - hi = _last_drawn_hi_segment; - lo = v; - } - } - else - { - lo = 0; - hi = _segments; - } - - _last_drawn_hi_segment = v; - - for ( int p = lo; p <= hi; p++ ) - { - Fl_Color c; - - if ( p <= v ) - { - if ( p == clipv ) - c = fl_color_average( FL_YELLOW, div_color( p ), 0.40 ); - else - c = div_color( p ); - } - else if ( p == pv ) - c = div_color( p ); - else - c = dim_div_color( p ); - - if ( ! active ) - c = fl_inactive( c ); - - int yy = 0; - int xx = 0; - - if ( type() == FL_HORIZONTAL ) - { - xx = X + p * bw; - fl_rectf( X + (p * bw), Y, bw, H, c ); - } - else - { - yy = Y + H - ((p+1) * bh); - fl_rectf( X, yy, W, bh, c ); - } - - if ( _pixels_per_segment >= 3 ) - { - fl_color( FL_DARK1 ); - - if ( type() == FL_HORIZONTAL ) - { - fl_line( xx, Y, xx, Y + H - 1 ); - } - else - { - fl_line( X, yy, X + W - 1, yy ); - } - } - - /* } */ - /* else */ - /* { */ - /* if ( type() == FL_HORIZONTAL ) */ - /* fl_draw_box( box(), X + (p * bw), Y, bw, H, c ); */ - /* else */ - /* fl_draw_box( box(), X, Y + H - ((p + 1) * bh), W, bh, c ); */ - /* } */ - } - - fl_pop_clip(); -} diff --git a/mixer/src/DPM.H b/mixer/src/DPM.H deleted file mode 100644 index 03f24bb..0000000 --- a/mixer/src/DPM.H +++ /dev/null @@ -1,107 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include // for FL_HORIZONTAL and FL_VERTICAL - -#include "Meter.H" - -class DPM : public Meter -{ - char peak_string[10]; - - int _segments; - int _pixels_per_segment; - int _last_drawn_hi_segment; - - float _value; - - int pos ( float v ) - { - float pv = deflection( v ) * ( _segments - 1 ); - - return pv; - } - - static float _dim; - static Fl_Color _gradient[]; - static Fl_Color _dim_gradient[]; - - Fl_Color - div_color ( int i ) - { - return _gradient[ i * 127 / _segments ]; - } - - Fl_Color - dim_div_color ( int i ) - { - return _dim_gradient[ i * 127 / _segments ]; - } - - -protected: - - virtual void draw_label ( void ); - virtual void draw ( void ); - virtual void resize ( int, int, int, int ); - - void bbox ( int &X, int &Y, int &W, int &H ); - -public: - - DPM ( int X, int Y, int W, int H, const char *L = 0 ); - - void value ( float v ) - { - if ( _value != v ) - { - if ( pos( v ) != pos( _value ) ) - Meter::value( v ); - } - - _value = v; - } - - float value ( void ) const - { - return _value; - } - - void pixels_per_segment ( int v ) { _pixels_per_segment = v; } - - float dim ( void ) const { return _dim; } - void dim ( float v ) { _dim = v; if ( visible_r() ) redraw(); } - - static - void - blend ( int nbreaks, int* b, Fl_Color *c ) - { - for ( int i = 0; i < nbreaks - 1; i++ ) - { - int k = 0; - for ( int j = b[i]; j <= b[i+1]; j++, k++ ) - _gradient[ j ] = fl_color_average( c[i+1], c[i], ( k ) / (float)(b[i+1] - b[i] )); - } - - for ( int i = 0; i < 128; i++ ) - _dim_gradient[ i ] = fl_color_average( FL_BLACK, _gradient[ i ], _dim ); - } -}; diff --git a/mixer/src/Gain_Module.C b/mixer/src/Gain_Module.C deleted file mode 100644 index ecd5fe1..0000000 --- a/mixer/src/Gain_Module.C +++ /dev/null @@ -1,142 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include - -#include "Gain_Module.H" - - - -Gain_Module::Gain_Module ( ) - : Module ( 50, 24, name() ) -{ - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - - { - Port p( this, Port::INPUT, Port::CONTROL, "Gain (dB)" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -70.0f; - p.hints.maximum = 6.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Mute" ); - p.hints.type = Port::Hints::BOOLEAN; - p.hints.ranged = true; - p.hints.minimum = 0.0f; - p.hints.maximum = 1.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - end(); - - log_create(); - - smoothing.sample_rate( sample_rate() ); -} - -Gain_Module::~Gain_Module ( ) -{ - delete (float*)control_input[0].buffer(); - delete (float*)control_input[1].buffer(); - log_destroy(); -} - - - -bool -Gain_Module::configure_inputs ( int n ) -{ - audio_input.clear(); - audio_output.clear(); -// control_input.clear(); - - for ( int i = 0; i < n; ++i ) - { - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - } - - return true; -} - -void -Gain_Module::handle_sample_rate_change ( nframes_t n ) -{ - smoothing.sample_rate( n ); -} - - - -/**********/ -/* Engine */ -/**********/ - -void -Gain_Module::process ( nframes_t nframes ) -{ - - if ( unlikely( bypass() ) ) - { - /* nothing to do */ - } - else - { - const float gt = DB_CO( control_input[1].control_value() ? -90.f : control_input[0].control_value() ); - - sample_t gainbuf[nframes]; - - bool use_gainbuf = smoothing.apply( gainbuf, nframes, gt ); - - if ( unlikely( use_gainbuf ) ) - { - for ( int i = audio_input.size(); i--; ) - { - if ( audio_input[i].connected() && audio_output[i].connected() ) - { - sample_t *out = (sample_t*)audio_input[i].buffer(); - - buffer_apply_gain_buffer( out, gainbuf, nframes ); - } - } - } - else - for ( int i = audio_input.size(); i--; ) - { - if ( audio_input[i].connected() && audio_output[i].connected() ) - { - buffer_apply_gain( (sample_t*)audio_input[i].buffer(), nframes, gt ); - } - } - } -} diff --git a/mixer/src/Gain_Module.H b/mixer/src/Gain_Module.H deleted file mode 100644 index a8bf764..0000000 --- a/mixer/src/Gain_Module.H +++ /dev/null @@ -1,50 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" -#include "dsp.h" - -class Gain_Module : public Module -{ - Value_Smoothing_Filter smoothing; - -public: - - Gain_Module ( ); - Gain_Module ( const Gain_Module & rhs ); - virtual ~Gain_Module ( ); - - const char *name ( void ) const { return "Gain"; } - - int can_support_inputs ( int n ) { return n; } - bool configure_inputs ( int n ); - - LOG_CREATE_FUNC( Gain_Module ); - - MODULE_CLONE_FUNC( Gain_Module ); - - virtual void handle_sample_rate_change ( nframes_t n ); - -protected: - - virtual void process ( nframes_t nframes ); - -}; diff --git a/mixer/src/Group.C b/mixer/src/Group.C deleted file mode 100644 index 1f57642..0000000 --- a/mixer/src/Group.C +++ /dev/null @@ -1,303 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include "Group.H" -#include "Chain.H" -#include "Mixer_Strip.H" -#include "Module.H" - -#include -extern char *instance_name; - -Group::Group ( ) -{ - _single =false; - _name = NULL; - _dsp_load = _load_coef = 0; -} - -Group::Group ( const char *name, bool single ) : Loggable ( !single ) -{ - _single = single; - _name = strdup(name); - _dsp_load = _load_coef = 0; - - // this->name( name ); - - /* FIXME: handle client creation error */ -/* if ( ! jack_name ) */ -/* { */ -/* _engine = NULL; */ - -/* // fl_alert( "Could not create JACK client. Perhaps the sound device already in use. In any event, now I'll die." ); */ -/* exit( 1 ); */ -/* // return false; */ -/* } */ -} - -Group::~Group ( ) -{ - DMESSAGE( "Destroying group" ); - - if ( _name ) - free( _name ); - - deactivate(); -} - - -void -Group::get ( Log_Entry &e ) const -{ - e.add( ":name", name() ); -} - -void -Group::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! ( strcmp( s, ":name" ) ) ) - { - bool add = false; - if (!_name ) - add = true; - - _name = strdup(v); - - if ( add ) - mixer->add_group(this); - } - } -} - - - -/*************/ -/* Callbacks */ -/*************/ - -void -Group::latency ( jack_latency_callback_mode_t mode ) -{ - for ( std::list::iterator i = strips.begin(); - i != strips.end(); - i++ ) - { - if ( (*i)->chain() ) - (*i)->chain()->set_latency(mode == JackCaptureLatency ? JACK::Port::Input : JACK::Port::Output ); - } -} - -/* THREAD: RT */ -/** This is the jack xrun callback */ -int -Group::xrun ( void ) -{ - return 0; -} - -/* THREAD: RT */ -void -Group::freewheel ( bool starting ) -{ - if ( starting ) - DMESSAGE( "entering freewheeling mode" ); - else - DMESSAGE( "leaving freewheeling mode" ); -} - -/* THREAD: RT (non-RT) */ -int -Group::buffer_size ( nframes_t nframes ) -{ - recal_load_coef(); - - /* JACK calls this in the RT thread, even though it's a - * non-realtime operation. This mucks up our ability to do - * THREAD_ASSERT, so just lie and say this is the UI thread... */ - - _thread.set( "UI" ); - - for ( std::list::iterator i = strips.begin(); - i != strips.end(); - i++ ) - { - if ( (*i)->chain() ) - (*i)->chain()->buffer_size(nframes); - } - - _thread.set( "RT" ); - - return 0; -} - -/* THREAD: ?? */ -void -Group::port_connect( jack_port_id_t a, jack_port_id_t b, int connect ) -{ - for ( std::list::iterator i = strips.begin(); - i != strips.end(); - i++ ) - { - if ( (*i)->chain() ) - (*i)->chain()->port_connect( a, b, connect); - } -} - - -/* THREAD: RT */ -int -Group::process ( nframes_t nframes ) -{ - jack_time_t then = jack_get_time(); - - /* FIXME: wrong place for this */ - _thread.set( "RT" ); - - if ( ! trylock() ) - { - /* the data structures we need to access here (tracks and - * their ports, but not track contents) may be in an - * inconsistent state at the moment. Just punt and drop this - * buffer. */ - ++_buffers_dropped; - return 0; - } - - - /* since feedback loops are forbidden and outputs are - * summed, we don't care what order these are processed - * in */ - for ( std::list::iterator i = strips.begin(); - i != strips.end(); - i++ ) - { - if ( (*i)->chain() ) - (*i)->chain()->process(nframes); - } - - unlock(); - - _dsp_load = (float)(jack_get_time() - then ) * _load_coef; - - return 0; -} - -void -Group::recal_load_coef ( void ) -{ - _load_coef = 1.0f / ( nframes() / (float)sample_rate() * 1000000.0 ); -} -int -Group::sample_rate_changed ( nframes_t srate ) -{ - recal_load_coef(); - - for ( std::list::iterator i = strips.begin(); - i != strips.end(); - i++ ) - { - if ( (*i)->chain() ) - (*i)->chain()->sample_rate_change(srate); - } - - return 0; -} - -/* TRHEAD: RT */ -void -Group::thread_init ( void ) -{ - _thread.set( "RT" ); -} - -/* THREAD: RT */ -void -Group::shutdown ( void ) -{ -} - -/*******************/ -/* Group interface */ -/*******************/ - -void -Group::name ( const char *n ) -{ - if ( _name ) - free( _name ); - - char ename[512]; - - _name = strdup( n ); - - if ( _single ) - snprintf( ename, sizeof(ename), "%s/%s", instance_name, n ); - else - snprintf( ename, sizeof(ename), "%s (%s)", instance_name, n ); - - if ( !active() ) - { - Client::init( ename ); - Module::set_sample_rate( sample_rate() ); - } - else - { - Client::name( ename ); - } -} - -void -Group::add ( Mixer_Strip *o ) -{ - lock(); - if ( ! active() ) - { - /* to call init */ - char *n = strdup(name()); - name(n); - free(n); - } - if ( o->chain() ) - o->chain()->thaw_ports(); - - strips.push_back(o); - unlock(); -} - -void -Group::remove ( Mixer_Strip *o ) -{ - lock(); - strips.remove(o); - if ( o->chain() ) - o->chain()->freeze_ports(); - if ( strips.size() == 0 && active() ) - { - Client::close(); - } - unlock(); -} - diff --git a/mixer/src/Group.H b/mixer/src/Group.H deleted file mode 100644 index 5d3dd3d..0000000 --- a/mixer/src/Group.H +++ /dev/null @@ -1,102 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -class Mixer_Strip; - -#include "Mutex.H" - -class Port; - -#include "JACK/Client.H" - -#include "Thread.H" -#include "Loggable.H" - -class Group : public Loggable, public JACK::Client, public Mutex -{ - bool _single; - char *_name; - - Thread _thread; /* only used for thread checking */ - - int _buffers_dropped; /* buffers dropped because of locking */ -/* int _buffers_dropped; /\* buffers dropped because of locking *\/ */ - - volatile float _dsp_load; - float _load_coef; - - int sample_rate_changed ( nframes_t srate ); - void shutdown ( void ); - int process ( nframes_t nframes ); - int xrun ( void ); - void freewheel ( bool yes ); - int buffer_size ( nframes_t nframes ); - void thread_init ( void ); - void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ); - virtual void latency ( jack_latency_callback_mode_t mode ); - - /* not allowed */ - Group ( const Group &rhs ); - Group & operator = ( const Group &rhs ); - - void request_locate ( nframes_t frame ); - - void recal_load_coef ( void ); - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - -private: - - friend class Port; - friend class Transport; - -public: - - LOG_CREATE_FUNC( Group ); - - float dsp_load ( void ) const { return _dsp_load; } - int nstrips ( void ) const { return strips.size(); } - int dropped ( void ) const { return _buffers_dropped; } - - Group ( ); - Group ( const char * name, bool single ); - virtual ~Group ( ); - - bool single ( void ) const { return _single; } - - const char * name ( void ) const { return _name; } - void name ( const char *n ); - - std::list strips; - - /* static void process ( nframes_t nframes, void *v ); */ - /* void process ( nframes_t nframes ); */ - - void add (Mixer_Strip*); - void remove (Mixer_Strip*); - - /* Engine *engine ( void ) { return _engine; } */ -}; - diff --git a/mixer/src/JACK_Module.C b/mixer/src/JACK_Module.C deleted file mode 100644 index 199f75c..0000000 --- a/mixer/src/JACK_Module.C +++ /dev/null @@ -1,730 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" - -#include - -#include -#include -#include -#include - -#include "dsp.h" - -#include "Chain.H" - -#include "JACK_Module.H" -#include - -#include -#include - -#include -#include -#include - -static Fl_PNG_Image *input_connector_image = NULL; -static Fl_PNG_Image *output_connector_image = NULL; - -extern char *instance_name; - -#include "Mixer.H" -#include "Group.H" - - -static JACK_Module *receptive_to_drop = NULL; - -const int MAX_PORTS = 16; - -JACK_Module::JACK_Module ( bool log ) - : Module ( 25, 25, name() ) -{ - _prefix = 0; - - _connection_handle_outputs[0][0] = 0; - _connection_handle_outputs[0][1] = 0; - _connection_handle_outputs[1][0] = 0; - _connection_handle_outputs[1][1] = 0; - - - align( FL_ALIGN_TOP | FL_ALIGN_INSIDE ); - - if ( log ) - { - /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ - { - Port p( this, Port::INPUT, Port::CONTROL, "Inputs" ); - p.hints.type = Port::Hints::INTEGER; - p.hints.minimum = 1; - p.hints.maximum = MAX_PORTS; - p.hints.ranged = true; - p.hints.visible = false; - - p.connect_to( new float ); - p.control_value_no_callback( 0 ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Outputs" ); - p.hints.type = Port::Hints::INTEGER; - p.hints.minimum = 1; - p.hints.maximum = MAX_PORTS; - p.hints.ranged = true; - p.hints.visible = false; - - p.connect_to( new float ); - p.control_value_no_callback( 0 ); - - add_port( p ); - } - - color( FL_DARK1 ); - - log_create(); - } - - - { Fl_Scalepack *o = new Fl_Scalepack( x() + Fl::box_dx(box()), - y() + Fl::box_dy(box()), - w() - Fl::box_dw(box()), - h() - Fl::box_dh(box()) ); - o->type( Fl_Pack::VERTICAL ); - o->spacing(0); - - - { Fl_Scalepack *o = new Fl_Scalepack( x() + Fl::box_dx(box()), - y() + Fl::box_dy(box()), - w(), - 24 - Fl::box_dh(box()) ); - o->type( Fl_Pack::HORIZONTAL ); - - o->spacing( 0 ); - - - { Fl_Box *o = input_connection_handle = new Fl_Box( x(), y(), 18, 18 ); - o->tooltip( "Drag and drop to make and break JACK connections."); - o->hide(); - o->image( input_connector_image ? input_connector_image : input_connector_image = new Fl_PNG_Image( "input_connector", img_io_input_connector_10x10_png, img_io_input_connector_10x10_png_len ) ); - - } - - { Fl_Box *o = new Fl_Box( x() + 10, y(), w() - 20, h() ); - Fl_Group::current()->resizable(o); - } - - - { Fl_Button *o = dec_button = new Fl_Button( 0, 0, 12, h(), "-" ); - o->callback( cb_button, this ); - o->labelsize(10); - o->labelfont( FL_HELVETICA_BOLD ); - o->hide(); - } - { Fl_Button *o = inc_button = new Fl_Button( 0,0, 12, h(), "+" ); - o->labelsize(10); - o->labelfont( FL_HELVETICA_BOLD ); - o->callback( cb_button, this ); - o->hide(); - } - - { Fl_Box *o = output_connection_handle = new Fl_Box( x(), y(), 12, 12 ); - o->tooltip( "Drag and drop to make and break JACK connections."); - o->image( output_connector_image ? output_connector_image : output_connector_image = new Fl_PNG_Image( "output_connector", img_io_output_connector_10x10_png, img_io_output_connector_10x10_png_len ) ); - o->hide(); - } - - { Fl_Box *o = output_connection2_handle = new Fl_Box( x(), y(), 12, 12 ); - o->tooltip( "Drag and drop to make and break JACK connections."); - o->image( output_connector_image ? output_connector_image : output_connector_image = new Fl_PNG_Image( "output_connector", img_io_output_connector_10x10_png, img_io_output_connector_10x10_png_len ) ); - o->hide(); - } - - o->end(); - } - - { - Fl_Browser *o = connection_display = new Fl_Browser( 0, 0, w(), h() ); - o->has_scrollbar(Fl_Browser_::VERTICAL); - o->textsize( 10 ); - o->textcolor( FL_LIGHT3 ); - o->textfont( FL_COURIER ); - o->box( FL_FLAT_BOX ); - o->color( FL_DARK1 ); - // o->color( fl_color_add_alpha( fl_rgb_color( 10, 10, 10 ), 100 )); - - Fl_Group::current()->resizable(o); - } - o->end(); - resizable(o); - } - end(); -} - -JACK_Module::~JACK_Module ( ) -{ - log_destroy(); - configure_inputs( 0 ); - configure_outputs( 0 ); - if ( _prefix ) - free( _prefix ); -} - - - -void -JACK_Module::draw ( void ) -{ - Module::draw(); - if ( this == receptive_to_drop ) - { - Fl_Widget *o = input_connection_handle; - fl_draw_box( FL_OVAL_BOX, o->x(), o->y(), o->w(), o->h(), fl_color_add_alpha( FL_GREEN, 127 ) ); - } -} - -static std::list -get_connections_for_ports ( std::vector ports ) -{ - std::list names; - - for ( unsigned int i = 0; i < ports.size(); ++i ) - { - const char **connections = ports[i].jack_port()->connections(); - - if ( ! connections ) - return names; - - bool is_output = ports[i].jack_port()->direction() == JACK::Port::Output; - - for ( const char **c = connections; *c; c++ ) - { - char *client_id = 0; - char *strip_name = 0; - // char *client_name = 0; - - if ( 2 == sscanf( *c, "Non-Mixer.%m[^:/]/%m[^:]:", &client_id, &strip_name ) ) - { - free( client_id ); - char *s = NULL; - asprintf( &s, "%s%s", is_output ? "@r" : "", strip_name ); - free( strip_name ); - strip_name = s; - } - else if ( 2 == sscanf( *c, "Non-Mixer.%m[^:(] (%m[^:)]):", &client_id, &strip_name ) ) - { - free( client_id ); - char *s = NULL; - asprintf( &s, "%s%s", is_output ? "@r" : "", strip_name ); - free( strip_name ); - strip_name = s; - } - else if ( 2 == sscanf( *c, "Non-Timeline.%m[^:/]:%m[^/]/", &client_id, &strip_name ) ) - { - free( client_id ); - char *s = NULL; - asprintf( &s, "@C2%s%s", is_output ? "@r" : "", strip_name ); - free( strip_name ); - strip_name = s; - } - else if ( 2 == sscanf( *c, "Non-DAW.%m[^:/]:%m[^/]/", &client_id, &strip_name ) ) - { - free( client_id ); - char *s = NULL; - asprintf( &s, "@C2%s%s", is_output ? "@r" : "", strip_name ); - free( strip_name ); - strip_name = s; - } - else if ( 1 == sscanf( *c, "%m[^:]:", &strip_name ) ) - { - char *s = NULL; - asprintf( &s, "@C3%s%s", is_output ? "@r" : "", strip_name ); - free( strip_name ); - strip_name = s; - } - else - { - continue; - } - - for ( std::list::const_iterator j = names.begin(); - j != names.end(); - j++ ) - { - if ( !strcmp( j->c_str(), strip_name ) ) - { - goto skip; - } - } - - names.push_back( strip_name ); - - skip: - free( strip_name ); - - ; - - } - } - - names.sort(); - return names; -} - -void -JACK_Module::update_connection_status ( void ) -{ - /* do nothing when running in noui mode, as ->add will call some - * font measurement stuff which attempts to open the X display. */ - if ( ! fl_display ) - { - return; - } - - std::list output_names = get_connections_for_ports( aux_audio_output ); - std::list input_names = get_connections_for_ports( aux_audio_input ); - - connection_display->clear(); - - int n = 0; - for ( std::list::const_iterator j = input_names.begin(); - j != input_names.end(); - j++ ) - { - connection_display->add( j->c_str() ); - n++; - } - for ( std::list::const_iterator j = output_names.begin(); - j != output_names.end(); - j++ ) - { - connection_display->add( j->c_str() ); - n++; - } - - /* limit number of lines displayed */ - if ( n > 15 ) - n = 15; - - if ( n > 0 ) - size( w(), 26 + ( n * ( connection_display->incr_height() ) ) ); - else - size( w(), 24 ); - - parent()->parent()->redraw(); -} - -void -JACK_Module::cb_button ( Fl_Widget *w, void *v ) -{ - ((JACK_Module*)v)->cb_button( w ); -} - -void -JACK_Module::cb_button( Fl_Widget *w ) -{ - int n = audio_output.size(); - - Logger log(this); - - if ( w == dec_button ) - { - --n; - } - else if ( w == inc_button ) - { - ++n; - } - - control_input[1].control_value( n ); -} - -int -JACK_Module::can_support_inputs ( int ) -{ - return audio_output.size(); -} - - -void -JACK_Module::remove_aux_audio_outputs ( void ) -{ - for ( unsigned int i = aux_audio_output.size(); i--; ) - { - aux_audio_output.back().jack_port()->shutdown(); - aux_audio_output.pop_back(); - } -} - -bool -JACK_Module::configure_inputs ( int n ) -{ - if ( n > 0 ) - { - output_connection_handle->show(); - } - - if ( n < 1 || n > MAX_PORTS ) - return false; - - int on = audio_input.size(); - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - if ( add_aux_audio_output(_prefix, i ) ) - { - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - } - } - - mixer->maybe_auto_connect_output(&aux_audio_output.back()); - } - else - { - for ( int i = on; i > n; --i ) - { - audio_input.back().disconnect(); - audio_input.pop_back(); - aux_audio_output.back().disconnect(); - aux_audio_output.back().jack_port()->shutdown(); - delete aux_audio_output.back().jack_port(); - aux_audio_output.pop_back(); - - } - } - - _connection_handle_outputs[0][0] = 0; - _connection_handle_outputs[0][1] = aux_audio_output.size(); - - if ( is_default() ) - control_input[0].control_value_no_callback( n ); - - return true; -} - -bool -JACK_Module::configure_outputs ( int n ) -{ - int on = audio_output.size(); - - if ( n > MAX_PORTS ) - return false; - - if ( n > 0 ) - { - input_connection_handle->show(); - } - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - if ( add_aux_audio_input(_prefix, i ) ) - { - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - } - } - - mixer->auto_connect(); - } - else - { - for ( int i = on; i > n; --i ) - { - audio_output.back().disconnect(); - audio_output.pop_back(); - aux_audio_input.back().disconnect(); - aux_audio_input.back().jack_port()->shutdown(); - delete aux_audio_input.back().jack_port(); - aux_audio_input.pop_back(); - } - } - - if ( is_default() ) - control_input[1].control_value_no_callback( n ); - - if ( n > 0 && is_default() ) - { - dec_button->show(); - inc_button->show(); - } - - return true; -} - - -bool -JACK_Module::initialize ( void ) -{ - return true; -} - -void -JACK_Module::handle_control_changed ( Port *p ) -{ -// THREAD_ASSERT( UI ); - - if ( 0 == strcmp( p->name(), "Inputs" ) ) - { - DMESSAGE( "Adjusting number of inputs (JACK outputs)" ); - configure_inputs( p->control_value() ); - if ( chain() ) - chain()->configure_ports(); - } - else if ( 0 == strcmp( p->name(), "Outputs" ) ) - { - DMESSAGE( "Adjusting number of outputs (JACK inputs)" ); - - if ( ! chain() ) - { - configure_outputs( p->control_value() ); - } - else if ( chain()->can_configure_outputs( this, p->control_value() ) ) - { - configure_outputs( p->control_value() ); - chain()->configure_ports(); - } - else - { - p->connected_port()->control_value( noutputs() ); - } - } - - Module::handle_control_changed( p ); -} - -int -JACK_Module::handle ( int m ) -{ - static unsigned long _event_state = 0; - - unsigned long evstate = Fl::event_state(); - - switch ( m ) - { - case FL_PUSH: - if ( Fl::event_inside( output_connection_handle ) || - Fl::event_inside( output_connection2_handle ) || - Fl::event_inside( input_connection_handle ) ) - { - _event_state = evstate; - return 1; - } - - return Module::handle(m) || 1; - - case FL_RELEASE: - Fl::selection_owner(0); - receptive_to_drop = NULL; - - if ( Fl::event_inside( output_connection_handle ) || - Fl::event_inside( output_connection2_handle ) || - Fl::event_inside( input_connection_handle ) ) - { - if ( _event_state & FL_BUTTON3 ) - { - /* was a right click */ - // TODO: Pop up connection menu. - } - } - - return Module::handle(m) || 1; - case FL_DRAG: - { - if ( Fl::event_is_click() ) - return 1; - - int connection_handle = -1; - if ( Fl::event_inside( output_connection_handle ) ) - connection_handle = 0; - if ( Fl::event_inside( output_connection2_handle ) ) - connection_handle = 1; - - if ( Fl::event_button1() && - connection_handle >= 0 - && ! Fl::selection_owner() ) - { - DMESSAGE( "initiation of drag" ); - - char *s = (char*)malloc(256); - s[0] = 0; - - for ( unsigned int i = _connection_handle_outputs[connection_handle][0]; - i < aux_audio_output.size() && i < _connection_handle_outputs[connection_handle][1]; ++i ) - { - char *s2; - asprintf(&s2, "jack.port://%s\r\n", - aux_audio_output[i].jack_port()->jack_name() ); - - s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 ); - strcat( s, s2 ); - - free( s2 ); - } - - Fl::copy(s, strlen(s) + 1, 0); - - Fl::selection_owner(this); - - free( s ); - - Fl::dnd(); - - return 1; - } - - return 1; - } - /* we have to prevent Fl_Group::handle() from getting these, otherwise it will mess up Fl::belowmouse() */ - case FL_MOVE: - if ( Fl::event_inside( output_connection_handle ) || - Fl::event_inside( output_connection2_handle ) || - Fl::event_inside( input_connection_handle ) ) - { - fl_cursor( FL_CURSOR_HAND ); - } - else - fl_cursor( FL_CURSOR_DEFAULT ); - - Module::handle(m); - return 1; - case FL_ENTER: - case FL_DND_ENTER: - Module::handle(m); - return 1; - case FL_LEAVE: - case FL_DND_LEAVE: - Module::handle(m); - if ( this == receptive_to_drop ) - { - receptive_to_drop = NULL; - redraw(); - } - fl_cursor( FL_CURSOR_DEFAULT ); - return 1; - case FL_DND_RELEASE: - Fl::selection_owner(0); - receptive_to_drop = NULL; - redraw(); - return 1; - case FL_DND_DRAG: - { - if ( this == receptive_to_drop ) - return 1; - - if ( aux_audio_input.size() ) - { - - receptive_to_drop = this; - redraw(); - return 1; - } - - return 0; - } - case FL_PASTE: - { - receptive_to_drop = NULL; - redraw(); - - if ( ! Fl::event_inside( this ) ) - return 0; - - /* NOW we get the text... */ - const char *text = Fl::event_text(); - - DMESSAGE( "Got drop text \"%s\"",text); - - if ( strncmp( text, "jack.port://", strlen( "jack.port://" ) ) ) - { - return 0; - } - - std::vector port_names; - - char *port_name; - int end; - while ( sscanf( text, "jack.port://%m[^\r\n]\r\n%n", &port_name, &end ) > 0 ) - { - DMESSAGE( "Scanning %s", port_name ); - port_names.push_back( port_name ); - free(port_name ); - - text += end; - } - - for ( unsigned int i = 0; i < aux_audio_input.size() && i < port_names.size(); i++) - { - const char *pn = port_names[i].c_str(); - - JACK::Port *ji = aux_audio_input[i].jack_port(); - - if ( ji->connected_to( pn ) ) - { - - DMESSAGE( "Disconnecting from \"%s\"", pn ); - ji->disconnect( pn ); - } - else - { - DMESSAGE( "Connecting to %s", pn ); - ji->connect( pn ); - } - } - - Fl::selection_owner(0); - return 1; - } - } - - return Module::handle(m); -} - - -/**********/ -/* Engine */ -/**********/ - -void -JACK_Module::process ( nframes_t nframes ) -{ - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - { - if ( audio_input[i].connected() ) - { - buffer_copy( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), - (sample_t*)audio_input[i].buffer(), - nframes ); - } - - } - - for ( unsigned int i = 0; i < audio_output.size(); ++i ) - { - if ( audio_output[i].connected() ) - { - buffer_copy( (sample_t*)audio_output[i].buffer(), - (sample_t*)aux_audio_input[i].jack_port()->buffer(nframes), - nframes ); - } - } -} diff --git a/mixer/src/JACK_Module.H b/mixer/src/JACK_Module.H deleted file mode 100644 index 25e3d97..0000000 --- a/mixer/src/JACK_Module.H +++ /dev/null @@ -1,87 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -class Fl_Box; -class Fl_Browser; -#include "Module.H" -#include "JACK/Port.H" -#include - -class JACK_Module : public Module -{ - char *_prefix; - -protected: - - void prefix ( const char *s ) - { - if ( _prefix ) - free( _prefix ); - - _prefix = NULL; - - if ( s ) - _prefix = strdup( s ); - } - - Fl_Button * dec_button; - Fl_Button * inc_button; - Fl_Browser * connection_display; - Fl_Box * input_connection_handle; - Fl_Box * output_connection_handle; - Fl_Box * output_connection2_handle; - - static void cb_button ( Fl_Widget *w, void *v ); - void cb_button ( Fl_Widget *w ); - -protected: - - unsigned int _connection_handle_outputs[2][2]; - -public: - - void update_connection_status ( void ); - - JACK_Module ( bool log = true ); - virtual ~JACK_Module ( ); - - virtual const char *basename ( void ) const { return "JACK"; } - virtual const char *name ( void ) const { return "JACK"; } - virtual bool initialize ( void ); - - virtual void draw ( void ); - virtual int handle ( int m ); - - virtual int can_support_inputs ( int ); - void remove_aux_audio_outputs ( void ); - virtual bool configure_inputs ( int n ); - virtual bool configure_outputs ( int n ); - - virtual void handle_control_changed ( Port *p ); - - LOG_CREATE_FUNC( JACK_Module ); - - -protected: - - virtual void process ( nframes_t nframes ); - -}; diff --git a/mixer/src/LADSPAInfo.C b/mixer/src/LADSPAInfo.C deleted file mode 100644 index 8fc611e..0000000 --- a/mixer/src/LADSPAInfo.C +++ /dev/null @@ -1,828 +0,0 @@ -// -// LADSPAInfo.C - Class for indexing information on LADSPA Plugins -// -// Copyleft (C) 2002 Mike Rawes -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// - -// #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define HAVE_LIBLRDF 1 -#ifdef HAVE_LIBLRDF -#include -#endif - -#include "LADSPAInfo.h" - -using namespace std; - -LADSPAInfo::LADSPAInfo(bool override, - const char *path_list) -{ - if (strlen(path_list) > 0) { - m_ExtraPaths = strdup(path_list); - } else { - m_ExtraPaths = NULL; - } - m_LADSPAPathOverride = override; - - RescanPlugins(); -} - -LADSPAInfo::~LADSPAInfo() -{ - CleanUp(); -} - -void -LADSPAInfo::RescanPlugins(void) -{ -// Clear out what we've got - CleanUp(); - - if (!m_LADSPAPathOverride) { - // Get $LADPSA_PATH, if available - char *ladspa_path = getenv("LADSPA_PATH"); - if (ladspa_path) { - ScanPathList(ladspa_path, &LADSPAInfo::ExaminePluginLibrary); - - } else { - - cerr << "WARNING: LADSPA_PATH environment variable not set" << endl; - cerr << " Assuming /usr/lib/ladspa:/usr/local/lib/ladspa" << endl; - - ScanPathList("/usr/lib/ladspa:/usr/local/lib/ladspa", &LADSPAInfo::ExaminePluginLibrary); - } - } - -// Check any supplied extra paths - if (m_ExtraPaths) { - ScanPathList(m_ExtraPaths, &LADSPAInfo::ExaminePluginLibrary); - } - -// Do we have any plugins now? - if (m_Plugins.size() == 0) { - cerr << "WARNING: No plugins found" << endl; - } else { - cerr << m_Plugins.size() << " plugins found in " << m_Libraries.size() << " libraries" << endl; - -#ifdef HAVE_LIBLRDF - // Got some plugins. Now search for RDF data - lrdf_init(); - - char *rdf_path = getenv("LADSPA_RDF_PATH"); - - if (rdf_path) { - // Examine rdf info - ScanPathList(rdf_path, &LADSPAInfo::ExamineRDFFile); - - } else { - cerr << "WARNING: LADSPA_RDF_PATH environment variable not set" << endl; - cerr << " Assuming /usr/share/ladspa/rdf:/usr/local/share/ladspa/rdf" << endl; - - // Examine rdf info - ScanPathList("/usr/share/ladspa/rdf:/usr/local/share/ladspa/rdf", &LADSPAInfo::ExamineRDFFile); - } - MetadataRDFDescend(LADSPA_BASE "Plugin", 0); - - // See which plugins were not added to an rdf group, and add them - // all into the top level 'LADSPA' one - list rdf_p; - - // Get indices of plugins added to groups - for (vector::iterator ri = m_RDFURIs.begin(); ri != m_RDFURIs.end(); ri++) { - rdf_p.insert(rdf_p.begin(), ri->Plugins.begin(), ri->Plugins.end()); - } - - // Add all uncategorized plugins to top level group, subclassed by their - // library's basename. - rdf_p.unique(); - rdf_p.sort(); - unsigned long last_p = 0; - for (list::iterator p = rdf_p.begin(); p != rdf_p.end(); p++) { - if ((*p - last_p) > 1) { - for (unsigned long i = last_p + 1; i < *p; i++) { - // URI 0 is top-level "LADSPA" group - m_RDFURIs[0].Plugins.push_back(i); - } - } - last_p = *p; - } - while (++last_p < m_Plugins.size()) { - // URI 0 is top-level "LADSPA" group - m_RDFURIs[0].Plugins.push_back(last_p); - } - - lrdf_cleanup(); -#else - // No RDF. Add all plugins to top-level group - RDFURIInfo ri; - - ri.URI = ""; - ri.Label = "LADSPA"; - - m_RDFURIs.push_back(ri); - m_RDFLabelLookup["LADSPA"] = 0; - - for (unsigned long i = 0; i < m_Plugins.size(); i++) { - // Add plugin index - m_RDFURIs[0].Plugins.push_back(i); - } -#endif - } -} - -void -LADSPAInfo::UnloadAllLibraries(void) -{ -// Blank descriptors - for (vector::iterator i = m_Plugins.begin(); - i != m_Plugins.end(); i++) { - if (i->Descriptor) i->Descriptor = NULL; - } -// Unload DLLs, - for (vector::iterator i = m_Libraries.begin(); - i != m_Libraries.end(); i++) { - if (i->Handle) { - dlclose(i->Handle); - i->Handle = NULL; - } - i->RefCount = 0; - } -} - -const LADSPA_Descriptor * -LADSPAInfo::GetDescriptorByID(unsigned long unique_id) -{ - if (m_IDLookup.find(unique_id) == m_IDLookup.end()) { - cerr << "LADSPA Plugin ID " << unique_id << " not found!" << endl; - return NULL; - } - -// Got plugin index - unsigned long plugin_index = m_IDLookup[unique_id]; - - PluginInfo *pi = &(m_Plugins[plugin_index]); - LibraryInfo *li = &(m_Libraries[pi->LibraryIndex]); - - if (!(pi->Descriptor)) { - LADSPA_Descriptor_Function desc_func = GetDescriptorFunctionForLibrary(pi->LibraryIndex); - if (desc_func) pi->Descriptor = desc_func(pi->Index); - } - - if (pi->Descriptor) { - - // Success, so increment ref counter for library - li->RefCount++; - } - - return pi->Descriptor; -} - -void -LADSPAInfo::DiscardDescriptorByID(unsigned long unique_id) -{ - if (m_IDLookup.find(unique_id) == m_IDLookup.end()) { - cerr << "LADSPA Plugin ID " << unique_id << " not found!" << endl; - } else { - - // Get plugin index - unsigned long plugin_index = m_IDLookup[unique_id]; - - PluginInfo *pi = &(m_Plugins[plugin_index]); - LibraryInfo *li = &(m_Libraries[pi->LibraryIndex]); - - pi->Descriptor = NULL; - - // Decrement reference counter for library, and unload if last - if (li->RefCount > 0) { - li->RefCount--; - if (li->RefCount == 0) { - - // Unload library - dlclose(li->Handle); - li->Handle = NULL; - } - } - } -} - -// **************************************************************************** -// ** SSM Specific Functions ** -// **************************************************************************** - -unsigned long -LADSPAInfo::GetIDFromFilenameAndLabel(std::string filename, - std::string label) -{ - bool library_loaded = false; - - if (m_FilenameLookup.find(filename) == m_FilenameLookup.end()) { - cerr << "LADSPA Library " << filename << " not found!" << endl; - return 0; - } - - unsigned long library_index = m_FilenameLookup[filename]; - - if (!(m_Libraries[library_index].Handle)) library_loaded = true; - - LADSPA_Descriptor_Function desc_func = GetDescriptorFunctionForLibrary(library_index); - - if (!desc_func) { - return 0; - } - -// Search for label in library - const LADSPA_Descriptor *desc; - for (unsigned long i = 0; (desc = desc_func(i)) != NULL; i++) { - string l = desc->Label; - if (l == label) { - - // If we had to load the library, unload it - unsigned long id = desc->UniqueID; - if (library_loaded) { - dlclose(m_Libraries[library_index].Handle); - m_Libraries[library_index].Handle = NULL; - } - return id; - } - } - - cerr << "Plugin " << label << " not found in library " << filename << endl; - return 0; -} - -const vector -LADSPAInfo::GetMenuList(void) -{ - m_SSMMenuList.clear(); - - DescendGroup("", "LADSPA", 1); - - return m_SSMMenuList; -} - -const vector -LADSPAInfo::GetPluginInfo(void) -{ - return m_Plugins; -} - -unsigned long -LADSPAInfo::GetPluginListEntryByID(unsigned long unique_id) -{ - unsigned long j = 0; - for (vector::iterator i = m_SSMMenuList.begin(); - i != m_SSMMenuList.end(); i++, j++) { - if (i->UniqueID == unique_id) return j; - } - return m_SSMMenuList.size(); -} - -// **************************************************************************** -// ** Private Member Functions ** -// **************************************************************************** - -// Build a list of plugins by group, suitable for SSM LADSPA Plugin drop-down -// The top-level "LADSPA" group is not included - -void -LADSPAInfo::DescendGroup(string prefix, - const string group, - unsigned int depth) -{ - list groups = GetSubGroups(group); - - if (prefix.length() > 0) { - // Add an explicit '/' as we're creating sub-menus from groups - prefix += "/"; - } - - for (list::iterator g = groups.begin(); g != groups.end(); g++) { - string name; - - // Escape '/' and '|' characters - size_t x = g->find_first_of("/|"); - if (x == string::npos) { - name = *g; - } else { - size_t last_x = 0; - while (x < string::npos) { - name += g->substr(last_x, x - last_x) + '\\' + (*g)[x]; - last_x = x + 1; - x = g->find_first_of("/|", x + 1); - } - name += g->substr(last_x, x - last_x); - } - - DescendGroup(prefix + name, *g, depth + 1); - } - if (m_RDFLabelLookup.find(group) != m_RDFLabelLookup.end()) { - unsigned long uri_index = m_RDFLabelLookup[group]; - - // Create group for unclassified plugins - if (prefix.length() == 0) { - prefix = "Unclassified/"; - depth = depth + 1; - } - - // Temporary list (for sorting the plugins by name) - list plugins; - - for (vector::iterator p = m_RDFURIs[uri_index].Plugins.begin(); - p != m_RDFURIs[uri_index].Plugins.end(); p++) { - - PluginInfo *pi = &(m_Plugins[*p]); - string name; - - // Escape '/' and '|' characters - size_t x = pi->Name.find_first_of("/|"); - if (x == string::npos) { - name = pi->Name; - } else { - size_t last_x = 0; - while (x < string::npos) { - name += pi->Name.substr(last_x, x - last_x) + '\\' + pi->Name[x]; - last_x = x + 1; - x = pi->Name.find_first_of("/|", x + 1); - } - name += pi->Name.substr(last_x, x - last_x); - } - - PluginEntry pe; - - pe.Depth = depth; - pe.UniqueID = pi->UniqueID; - pe.Name = name; - pe.Category = prefix; - pe.Category = pe.Category.substr(0, pe.Category.size()-1); - - - plugins.push_back(pe); - } - plugins.sort(); - - // Deal with duplicates by numbering them - for (list::iterator i = plugins.begin(); - i != plugins.end(); ) { - string name = i->Name; - - i++; - unsigned long n = 2; - while ((i != plugins.end()) && (i->Name == name)) { - stringstream s; - s << n; - i->Name = name + " (" + s.str() + ")"; - n++; - i++; - } - } - - // Add all ordered entries to the Menu List - // This ensures that plugins appear after groups - for (list::iterator p = plugins.begin(); p != plugins.end(); p++) { - m_SSMMenuList.push_back(*p); - } - } -} - -// Get list of groups that are within given group. The root group is -// always "LADSPA" -list -LADSPAInfo::GetSubGroups(const string group) -{ - list groups; - unsigned long uri_index; - - if (m_RDFLabelLookup.find(group) == m_RDFLabelLookup.end()) { - return groups; - } else { - uri_index = m_RDFLabelLookup[group]; - } - - for (vector::iterator sg = m_RDFURIs[uri_index].Children.begin(); - sg != m_RDFURIs[uri_index].Children.end(); sg++) { - groups.push_back(m_RDFURIs[*sg].Label); - } - - groups.sort(); - - return groups; -} - -// Unload any loaded DLLs and clear vectors etc -void -LADSPAInfo::CleanUp(void) -{ - m_MaxInputPortCount = 0; - - m_IDLookup.clear(); - m_Plugins.clear(); - -// Unload loaded dlls - for (vector::iterator i = m_Libraries.begin(); - i != m_Libraries.end(); i++) { - if (i->Handle) dlclose(i->Handle); - } - - m_Libraries.clear(); - m_Paths.clear(); - - m_RDFURILookup.clear(); - m_RDFURIs.clear(); - - if (m_ExtraPaths) { - free(m_ExtraPaths); - m_ExtraPaths = NULL; - } -} - -// Given a colon-separated list of paths, examine the contents of each -// path, examining any regular files using the given member function, -// which currently can be: -// -// ExaminePluginLibrary - add plugin library info from plugins -// ExamineRDFFile - add plugin information from .rdf/.rdfs files -void -LADSPAInfo::ScanPathList(const char *path_list, - void (LADSPAInfo::*ExamineFunc)(const string, - const string)) -{ - const char *start; - const char *end; - int extra; - char *path; - string basename; - DIR *dp; - struct dirent *ep; - struct stat sb; - -// This does the same kind of thing as strtok, but strtok won't -// like the const - start = path_list; - while (*start != '\0') { - while (*start == ':') start++; - end = start; - while (*end != ':' && *end != '\0') end++; - - if (end - start > 0) { - extra = (*(end - 1) == '/') ? 0 : 1; - path = (char *)malloc(end - start + 1 + extra); - if (path) { - strncpy(path, start, end - start); - if (extra == 1) path[end - start] = '/'; - path[end - start + extra] = '\0'; - - dp = opendir(path); - if (!dp) { - cerr << "WARNING: Could not open path " << path << endl; - } else { - while ((ep = readdir(dp))) { - - // Stat file to get type - basename = ep->d_name; - if (!stat((path + basename).c_str(), &sb)) { - - // We only want regular files - if (S_ISREG(sb.st_mode)) (*this.*ExamineFunc)(path, basename); - } - } - closedir(dp); - } - free(path); - } - } - start = end; - } -} - -// Check given file is a valid LADSPA Plugin library -// -// If so, add path, library and plugin info -// to the m_Paths, m_Libraries and m_Plugins vectors. -// -void -LADSPAInfo::ExaminePluginLibrary(const string path, - const string basename) -{ - void *handle; - LADSPA_Descriptor_Function desc_func; - const LADSPA_Descriptor *desc; - string fullpath = path + basename; - -// We're not executing any code, so be lazy about resolving symbols - handle = dlopen(fullpath.c_str(), RTLD_LAZY); - - if (!handle) { - cerr << "WARNING: File " << fullpath - << " could not be examined" << endl; - cerr << "dlerror() output:" << endl; - cerr << dlerror() << endl; - } else { - - // It's a DLL, so now see if it's a LADSPA plugin library - desc_func = (LADSPA_Descriptor_Function)dlsym(handle, - "ladspa_descriptor"); - if (!desc_func) { - - // Is DLL, but not a LADSPA one - cerr << "WARNING: DLL " << fullpath - << " has no ladspa_descriptor function" << endl; - cerr << "dlerror() output:" << endl; - cerr << dlerror() << endl; - } else { - - // Got ladspa_descriptor, so we can now get plugin info - bool library_added = false; - unsigned long i = 0; - desc = desc_func(i); - while (desc) { - - // First, check that it's not a dupe - if (m_IDLookup.find(desc->UniqueID) != m_IDLookup.end()) { - unsigned long plugin_index = m_IDLookup[desc->UniqueID]; - unsigned long library_index = m_Plugins[plugin_index].LibraryIndex; - unsigned long path_index = m_Libraries[library_index].PathIndex; - - cerr << "WARNING: Duplicated Plugin ID (" - << desc->UniqueID << ") found:" << endl; - - cerr << " Plugin " << m_Plugins[plugin_index].Index - << " in library: " << m_Paths[path_index] - << m_Libraries[library_index].Basename - << " [First instance found]" << endl; - cerr << " Plugin " << i << " in library: " << fullpath - << " [Duplicate not added]" << endl; - } else { - if (CheckPlugin(desc)) { - - // Add path if not already added - unsigned long path_index; - vector::iterator p = find(m_Paths.begin(), m_Paths.end(), path); - if (p == m_Paths.end()) { - path_index = m_Paths.size(); - m_Paths.push_back(path); - } else { - path_index = p - m_Paths.begin(); - } - - // Add library info if not already added - if (!library_added) { - LibraryInfo li; - li.PathIndex = path_index; - li.Basename = basename; - li.RefCount = 0; - li.Handle = NULL; - m_Libraries.push_back(li); - - library_added = true; - } - - - // Add plugin info - PluginInfo pi; - pi.LibraryIndex = m_Libraries.size() - 1; - pi.Index = i; - pi.UniqueID = desc->UniqueID; - pi.Label = desc->Label; - pi.Name = desc->Name; - pi.Descriptor = NULL; - pi.Maker = desc->Maker; - pi.AudioInputs = 0; - pi.AudioOutputs = 0; - - // Find number of input ports - unsigned long in_port_count = 0; - for (unsigned long p = 0; p < desc->PortCount; p++) { - if (LADSPA_IS_PORT_INPUT(desc->PortDescriptors[p])) { - in_port_count++; - if ( LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[p] ) ) - pi.AudioInputs++; - } - } - for (unsigned long p = 0; p < desc->PortCount; p++) { - if (LADSPA_IS_PORT_OUTPUT(desc->PortDescriptors[p])) { - - if ( LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[p] ) ) - pi.AudioOutputs++; - } - } - - if (in_port_count > m_MaxInputPortCount) { - m_MaxInputPortCount = in_port_count; - - } - - m_Plugins.push_back(pi); - - // Add to index - m_IDLookup[desc->UniqueID] = m_Plugins.size() - 1; - - } else { - cerr << "WARNING: Plugin " << desc->UniqueID << " not added" << endl; - } - } - - - desc = desc_func(++i); - } - } - dlclose(handle); - } -} - -#ifdef HAVE_LIBLRDF -// Examine given RDF plugin meta-data file -void -LADSPAInfo::ExamineRDFFile(const std::string path, - const std::string basename) -{ - string fileuri = "file://" + path + basename; - - if (lrdf_read_file(fileuri.c_str())) { - cerr << "WARNING: File " << path + basename << " could not be parsed [Ignored]" << endl; - } -} - -// Recursively add rdf information for plugins that have been -// found from scanning LADSPA_PATH -void -LADSPAInfo::MetadataRDFDescend(const char * uri, - unsigned long parent) -{ - unsigned long this_uri_index; - -// Check URI not already added - if (m_RDFURILookup.find(uri) == m_RDFURILookup.end()) { - - // Not found - RDFURIInfo ri; - - ri.URI = uri; - - if (ri.URI == LADSPA_BASE "Plugin") { - - // Add top level group as "LADSPA" - // This will always happen, even if there are no .rdf files read by liblrdf - // or if there is no liblrdf support - ri.Label = "LADSPA"; - } else { - char * label = lrdf_get_label(uri); - if (label) { - ri.Label = label; - } else { - ri.Label = "(No label)"; - } - } - - // Add any instances found - lrdf_uris * instances = lrdf_get_instances(uri); - if (instances) { - for (unsigned long j = 0; j < instances->count; j++) { - unsigned long uid = lrdf_get_uid(instances->items[j]); - if (m_IDLookup.find(uid) != m_IDLookup.end()) { - ri.Plugins.push_back(m_IDLookup[uid]); - } - } - } - - lrdf_free_uris(instances); - - m_RDFURIs.push_back(ri); - this_uri_index = m_RDFURIs.size() - 1; - - m_RDFURILookup[ri.URI] = this_uri_index; - m_RDFLabelLookup[ri.Label] = this_uri_index; - - } else { - - // Already added - this_uri_index = m_RDFURILookup[uri]; - } - -// Only add parent - child info if this uri is NOT the first (root) uri - if (this_uri_index > 0) { - m_RDFURIs[this_uri_index].Parents.push_back(parent); - m_RDFURIs[parent].Children.push_back(this_uri_index); - } - - lrdf_uris * uris = lrdf_get_subclasses(uri); - - if (uris) { - for (unsigned long i = 0; i < uris->count; i++) { - MetadataRDFDescend(uris->items[i], this_uri_index); - } - } - - lrdf_free_uris(uris); -} -#endif - -bool -LADSPAInfo::CheckPlugin(const LADSPA_Descriptor *desc) -{ -#define test(t, m) { \ - if (!(t)) { \ - cerr << m << endl; \ - return false; \ - } \ -} - test(desc->instantiate, "WARNING: Plugin has no instatiate function"); - test(desc->connect_port, "WARNING: Warning: Plugin has no connect_port funciton"); - test(desc->run, "WARNING: Plugin has no run function"); - test(!(desc->run_adding != 0 && desc->set_run_adding_gain == 0), - "WARNING: Plugin has run_adding but no set_run_adding_gain"); - test(!(desc->run_adding == 0 && desc->set_run_adding_gain != 0), - "WARNING: Plugin has set_run_adding_gain but no run_adding"); - test(desc->cleanup, "WARNING: Plugin has no cleanup function"); - test(!LADSPA_IS_INPLACE_BROKEN(desc->Properties), - "WARNING: Plugin cannot use in place processing"); - test(desc->PortCount, "WARNING: Plugin has no ports"); - test(desc->Name, "WARNING: Plugin has no name" ); - - if ( strcmp( desc->Maker, "Tom Szilagyi" ) ) - { - /* The author of the TAP plugins has a very narrow - * interpretation of the HARD RT hint which differs from - * most everyone else, so we are left in the unfortunate - * position of having to ignore the hint for TAP plugins - * and consider them all RT safe */ - test(LADSPA_IS_HARD_RT_CAPABLE( desc->Properties ), "WARNING: Plugin is not RT capable" ); - } - - return true; -} - -LADSPA_Descriptor_Function -LADSPAInfo::GetDescriptorFunctionForLibrary(unsigned long library_index) -{ - LibraryInfo *li = &(m_Libraries[library_index]); - - if (!(li->Handle)) { - - // Need full path - string fullpath = m_Paths[li->PathIndex]; - fullpath.append(li->Basename); - - // Immediate symbol resolution, as plugin code is likely to be executed - li->Handle = dlopen(fullpath.c_str(), RTLD_NOW); - if (!(li->Handle)) { - - // Plugin library changed since last path scan - cerr << "WARNING: Plugin library " << fullpath << " cannot be loaded" << endl; - cerr << "Rescan of plugins recommended" << endl; - cerr << "dlerror() output:" << endl; - cerr << dlerror() << endl; - return NULL; - } - } - -// Got handle so now verify that it's a LADSPA plugin library - const LADSPA_Descriptor_Function desc_func = (LADSPA_Descriptor_Function)dlsym(li->Handle, - "ladspa_descriptor"); - if (!desc_func) { - - // Is DLL, but not a LADSPA one (changed since last path scan?) - cerr << "WARNING: DLL " << m_Paths[li->PathIndex] << li->Basename - << " has no ladspa_descriptor function" << endl; - cerr << "Rescan of plugins recommended" << endl; - cerr << "dlerror() output:" << endl; - cerr << dlerror() << endl; - - // Unload library - dlclose(li->Handle); - return NULL; - } - - return desc_func; -} diff --git a/mixer/src/LADSPAInfo.h b/mixer/src/LADSPAInfo.h deleted file mode 100644 index fbda43d..0000000 --- a/mixer/src/LADSPAInfo.h +++ /dev/null @@ -1,208 +0,0 @@ -// -// LADSPAInfo.h - Header file for LADSPA Plugin info class -// -// Copyleft (C) 2002 Mike Rawes -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// - -#ifndef __ladspa_info_h__ -#define __ladspa_info_h__ - -// #include - -#include -#include -#include -#include -#include - -class LADSPAInfo -{ -public: -// If override is false, examine $LADSPA_PATH -// Also examine supplied path list -// For all paths, add basic plugin information for later lookup, -// instantiation and so on. - LADSPAInfo(bool override = false, const char *path_list = ""); - -// Unload all loaded plugins and clean up - ~LADSPAInfo(); - -// ************************************************************************ -// Loading/Unloading plugin libraries -// -// At first, no library dlls are loaded. -// -// A plugin library may have more than one plugin descriptor. The -// descriptor is used to instantiate, activate, execute plugin instances. -// Administration of plugin instances are outwith the scope of this class, -// instead, descriptors are requested using GetDecriptorByID, and disposed -// of using DiscardDescriptorByID. -// -// Each library keeps a reference count of descriptors requested. A library -// is loaded when a descriptor is requested for the first time, and remains -// loaded until the number of discards matches the number of requests. - -// Rescan all paths in $LADSPA_PATH, as per constructor. -// This will also unload all libraries, and make any descriptors that -// have not been discarded with DiscardDescriptorByID invalid. - void RescanPlugins(void); - -// Unload all dlopened libraries. This will make any descriptors that -// have not been discarded with DiscardDescriptorByID invalid. - void UnloadAllLibraries(void); - -// Get descriptor of plugin with given ID. This increments the descriptor -// count for the corresponding library. - const LADSPA_Descriptor *GetDescriptorByID(unsigned long unique_id); - -// Notify that a descriptor corresponding to the given ID has been -// discarded. This decrements the descriptor count for the corresponding -// library. - void DiscardDescriptorByID(unsigned long unique_id); - -// ************************************************************************ -// SSM Specific options - -// Get unique ID of plugin identified by given library filename and label. -// This is for backwards compatibility with older versions of SSM where the -// path and label of the plugin was stored in the configuration - current -// versions store the Unique ID - unsigned long GetIDFromFilenameAndLabel(std::string filename, - std::string label); - -// Struct for plugin information returned by queries - struct PluginEntry - { - unsigned int Depth; - unsigned long UniqueID; - std::string Name; - std::string Category; - - bool operator<(const PluginEntry& pe) - { - return (Name GetMenuList(void); - - const std::vector GetPluginInfo(void); - -// Get the index in the above list for given Unique ID -// If not found, this returns the size of the above list - unsigned long GetPluginListEntryByID(unsigned long unique_id); - -// Get the number of input ports for the plugin with the most -// input ports - unsigned long GetMaxInputPortCount(void) { return m_MaxInputPortCount; } - -private: -// See LADSPAInfo.C for comments on these functions - void DescendGroup(std::string prefix, - const std::string group, - unsigned int depth); - std::list GetSubGroups(const std::string group); - - void CleanUp(void); - void ScanPathList(const char *path_list, - void (LADSPAInfo::*ExamineFunc)(const std::string, - const std::string)); - void ExaminePluginLibrary(const std::string path, - const std::string basename); - - bool CheckPlugin(const LADSPA_Descriptor *desc); - LADSPA_Descriptor_Function GetDescriptorFunctionForLibrary(unsigned long library_index); -#ifdef HAVE_LIBLRDF - void ExamineRDFFile(const std::string path, - const std::string basename); - void MetadataRDFDescend(const char *uri, - unsigned long parent); -#endif - -// For cached library information - struct LibraryInfo - { - unsigned long PathIndex; // Index of path in m_Paths - std::string Basename; // Filename - unsigned long RefCount; // Count of descriptors requested - void *Handle; // DLL Handle, NULL - }; - -// For cached RDF uri information - struct RDFURIInfo - { - std::string URI; // Full URI for use with lrdf - std::string Label; // Label - std::vector Parents; // Index of parents in m_RDFURIs - std::vector Children; // Indices of children in m_RDFURIs - std::vector Plugins; // Indices of plugins in m_Plugins - }; - -// Lookup maps - typedef std::map > IDMap; - - typedef std::map > StringMap; - - bool m_LADSPAPathOverride; - char *m_ExtraPaths; - -// LADSPA Plugin information database - std::vector m_Paths; - std::vector m_Libraries; - std::vector m_Plugins; - -// Plugin lookup maps - IDMap m_IDLookup; - -// RDF URI database - std::vector m_RDFURIs; - -// RDF URI lookup map - StringMap m_RDFURILookup; - -// RDF Label lookup map - StringMap m_RDFLabelLookup; - -// SSM specific data - std::vector m_SSMMenuList; - StringMap m_FilenameLookup; - unsigned long m_MaxInputPortCount; -}; - -#endif // __ladspa_info_h__ diff --git a/mixer/src/Meter.H b/mixer/src/Meter.H deleted file mode 100644 index ce61263..0000000 --- a/mixer/src/Meter.H +++ /dev/null @@ -1,101 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -/* Base class for all meters */ - -#include -#include -#include -#include "FL/test_press.H" - -class Meter : public Fl_Valuator -{ - - float _peak; - float _value; - -protected: - - virtual void draw ( void ) = 0; - virtual int handle ( int m ) - { - if ( m == FL_ENTER || m == FL_LEAVE ) - return 1; - else if ( m == FL_PUSH && test_press( FL_BUTTON1 )) - { - reset(); - return 1; - } - - return Fl_Valuator::handle( m ); - } - - float - deflection ( float db ) - { - float def = 0.0f; - - if ( db < -70.0f ) - def = 0.0f; - else if ( db < -60.0f ) - def = ( db + 70.0f ) * 0.25f; - else if ( db < -50.0f ) - def = ( db + 60.0f ) * 0.5f + 2.5f; - else if ( db < -40.0f ) - def = ( db + 50.0f ) * 0.75f + 7.5f; - else if ( db < -30.0f ) - def = ( db + 40.0f ) * 1.5f + 15.0f; - else if ( db < -20.0f ) - def = ( db + 30.0f ) * 2.0f + 30.0f; - else if ( db < 6.0f ) - def = ( db + 20.0f ) * 2.5f + 50.0f; - else - def = 115.0f; - - return def / 115.0f; - } - -public: - - Meter ( int X, int Y, int W, int H, const char *L = 0 ) : - Fl_Valuator( X, Y, W, H, L ) - { - _peak = _value = -80.0f; - } - - virtual ~Meter ( ) { } - - virtual void value ( float v ) - { - if ( visible_r() ) - damage( FL_DAMAGE_USER1 ); - - _value = v; - - if ( _value > _peak ) - _peak = _value; - } - - virtual float value ( void ) const { return _value; } - float peak ( void ) const { return _peak; } - - void reset ( void ) { _peak = -80.0f; redraw(); } - -}; diff --git a/mixer/src/Meter_Indicator_Module.C b/mixer/src/Meter_Indicator_Module.C deleted file mode 100644 index df23d3b..0000000 --- a/mixer/src/Meter_Indicator_Module.C +++ /dev/null @@ -1,267 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2010 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Meter_Indicator_Module.H" - -#include - -#include -#include -#include -#include -#include -#include - -#include "FL/Fl_Dial.H" -#include "FL/Fl_Labelpad_Group.H" -#include "FL/Fl_Scalepack.H" - -#include "Chain.H" -#include "DPM.H" - -#include "FL/test_press.H" - - - -Meter_Indicator_Module::Meter_Indicator_Module ( bool is_default ) - : Module ( is_default, 50, 100, name() ) -{ - box( FL_FLAT_BOX ); - color( FL_BLACK ); - - _disable_context_menu = false; - _pad = true; - control_value = 0; - - add_port( Port( this, Port::INPUT, Port::CONTROL ) ); - - control_input[0].hints.visible = false; - - dpm_pack = new Fl_Scalepack( x(), y(), w(), h() ); - dpm_pack->color( FL_BACKGROUND_COLOR ); - dpm_pack->box( FL_FLAT_BOX ); - dpm_pack->type( FL_HORIZONTAL ); - - end(); - - control_value = new float[1]; - *control_value = -70.0f; - - align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE ) ); - - clear_visible_focus(); -} - -Meter_Indicator_Module::~Meter_Indicator_Module ( ) -{ - if ( control_value ) - { - delete[] control_value; - control_value = NULL; - } - - log_destroy(); -} - - - -void -Meter_Indicator_Module::get ( Log_Entry &e ) const -{ - - Port *p = control_input[0].connected_port(); - Module *m = p->module(); - - e.add( ":module", m ); - e.add( ":port", m->control_output_port_index( p ) ); - - Module::get( e ); -} - -void -Meter_Indicator_Module::set ( Log_Entry &e ) -{ - Module::set( e ); - - int port = -1; - Module *module = NULL; - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":port" ) ) - { - port = atoi( v ); - } - else if ( ! strcmp( s, ":module" ) ) - { - int i; - sscanf( v, "%X", &i ); - Module *t = (Module*)Loggable::find( i ); - - assert( t ); - - module = t; - } - } - - if ( port >= 0 && module ) - control_input[0].connect_to( &module->control_output[port] ); -} - - - -void -Meter_Indicator_Module::update ( void ) -{ - if ( control_input[0].connected() ) - { - // A little hack to detect that the connected module's number - // of control outs has changed. - Port *p = control_input[0].connected_port(); - - if ( dpm_pack->children() != p->hints.dimensions ) - { -/* engine->lock(); */ - - dpm_pack->clear(); - - control_value = new float[p->hints.dimensions]; - - for ( int i = p->hints.dimensions; i--; ) - { - - DPM *dpm = new DPM( x(), y(), w(), h() ); - dpm->type( FL_VERTICAL ); - - dpm_pack->add( dpm ); - - control_value[i] = -70.0f; - dpm->value( -70.0f ); - } - -/* engine->unlock(); */ - } - else - { - for ( int i = 0; i < dpm_pack->children(); ++i ) - { - ((DPM*)dpm_pack->child( i ))->value( control_value[i] ); - control_value[i] = -70.0f; - } - } - } -} - -void -Meter_Indicator_Module::connect_to ( Port *p ) -{ - control_input[0].connect_to( p ); - - /* DPM *o = new DPM( 10, 10, 10, 10 ); */ - /* o->type( FL_VERTICAL ); */ - - /* dpm_pack->add( o ); */ - - redraw(); -} - - - -int -Meter_Indicator_Module::handle ( int m ) -{ - switch ( m ) - { - case FL_PUSH: - { - if ( Fl::event_button3() && _disable_context_menu ) - return 0; - - if ( test_press( FL_BUTTON1 ) ) - { - /* don't let Module::handle eat our click */ - return Fl_Group::handle( m ); - } - } - } - - return Module::handle( m ); -} - - - -void -Meter_Indicator_Module::handle_control_changed ( Port *p ) -{ - THREAD_ASSERT( UI ); - - /* The engine is already locked by the UI thread at this point in - the call-graph, so we can be sure that process() won't be - executed concurrently. */ - if ( p->connected() ) - { - p = p->connected_port(); - - if ( dpm_pack->children() != p->hints.dimensions ) - { - dpm_pack->clear(); - - control_value = new float[p->hints.dimensions]; - - for ( int i = p->hints.dimensions; i--; ) - { - DPM *dpm = new DPM( x(), y(), w(), h() ); - dpm->type( FL_VERTICAL ); - align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE ) ); - - dpm_pack->add( dpm ); - dpm_pack->redraw(); - - control_value[i] = -70.0f; - dpm->value( -70.0f ); - } - - redraw(); - } - } -} - -/**********/ -/* Engine */ -/**********/ - -void -Meter_Indicator_Module::process ( nframes_t ) -{ - if ( control_input[0].connected() ) - { - Port *p = control_input[0].connected_port(); - - for ( int i = 0; i < p->hints.dimensions; ++i ) - { - float dB = ((float*)control_input[0].buffer())[i]; - if ( dB > control_value[i]) - control_value[i] = dB; - } - } -} diff --git a/mixer/src/Meter_Indicator_Module.H b/mixer/src/Meter_Indicator_Module.H deleted file mode 100644 index 960d17c..0000000 --- a/mixer/src/Meter_Indicator_Module.H +++ /dev/null @@ -1,83 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" -#include -#include "JACK/Port.H" - -class Fl_Valuator; -class Fl_Scalepack; - -class Meter_Indicator_Module : public Module -{ - Fl_Scalepack *dpm_pack; - - - bool _pad; - - volatile float *control_value; - - bool _disable_context_menu; - -public: - - virtual void update ( void ); - - void disable_context_menu ( bool b ) { _disable_context_menu = b; } - - void handle_control_changed ( Port *p ); - - Meter_Indicator_Module ( bool is_default = false ); - virtual ~Meter_Indicator_Module ( ); - - bool allows_external_control ( void ) const { return false; } - const char *name ( void ) const { return "Meter Indicator"; } - - int can_support_inputs ( int ) { return 0; } - bool configure_inputs ( int ) { return false; } - - void pad ( bool v ) { _pad = v; } - - static void cb_handle ( Fl_Widget *w, void *v ); - void cb_handle ( Fl_Widget *w ); - - void connect_to ( Port *p ); - - LOG_CREATE_FUNC( Meter_Indicator_Module ); - - void process ( nframes_t ); - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - virtual void draw ( void ) - { -// draw_box(); - Fl_Group::draw(); - } - - virtual int handle ( int m ); - -private: - -}; diff --git a/mixer/src/Meter_Module.C b/mixer/src/Meter_Module.C deleted file mode 100644 index 30876b3..0000000 --- a/mixer/src/Meter_Module.C +++ /dev/null @@ -1,185 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" - -#include -#include -#include - -#include "FL/Fl_Scalepack.H" -#include "FL/test_press.H" - -#include "Meter_Module.H" -#include "DPM.H" -#include "JACK/Port.H" -#include "dsp.h" - - - -Meter_Module::Meter_Module ( ) - : Module ( 50, 100, name() ) -{ - box( FL_NO_BOX ); - dpm_pack = new Fl_Scalepack( x(), y(), w(), h() ); - dpm_pack->type( FL_HORIZONTAL ); - - control_value = 0; - - color( FL_BLACK ); - - end(); - - Port p( this, Port::OUTPUT, Port::CONTROL, "dB level" ); - p.hints.type = Port::Hints::LOGARITHMIC; - p.hints.ranged = true; - p.hints.maximum = 6.0f; - p.hints.minimum = -70.0f; - p.hints.dimensions = 1; - p.connect_to( new float[1] ); - p.control_value_no_callback( -70.0f ); - - add_port( p ); - - log_create(); -} - -Meter_Module::~Meter_Module ( ) -{ - if ( control_value ) - delete[] control_value; - - log_destroy(); -} - - - -void -Meter_Module::update ( void ) -{ - for ( int i = dpm_pack->children(); i--; ) - { - ((DPM*)dpm_pack->child( i ))->value( control_value[i] ); - control_value[i] = -70.0f; - } -} - -bool -Meter_Module::configure_inputs ( int n ) -{ - THREAD_ASSERT( UI ); - - int on = audio_input.size(); - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - DPM *dpm = new DPM( 0, 0, w(), h() ); - dpm->type( FL_VERTICAL ); - align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE ) ); - - dpm_pack->add( dpm ); - - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - - } - } - else - { - for ( int i = on; i > n; --i ) - { - DPM *dpm = (DPM*)dpm_pack->child( dpm_pack->children() - 1 ); - dpm_pack->remove( dpm ); - delete dpm; - - audio_input.back().disconnect(); - audio_input.pop_back(); - audio_output.back().disconnect(); - audio_output.pop_back(); - } - } - - control_output[0].hints.dimensions = n; - delete[] (float*)control_output[0].buffer(); - { - float *f = new float[n]; - - for ( int i = n; i--; ) - f[i] = -70.0f; - - control_output[0].connect_to( f ); - } - - if ( control_value ) - delete [] control_value; - - control_value = new float[n]; - for ( int i = n; i--; ) - control_value[i] = -70.0f; - - if ( control_output[0].connected() ) - control_output[0].connected_port()->module()->handle_control_changed( control_output[0].connected_port() ); - - return true; -} - - - -int -Meter_Module::handle ( int m ) -{ - switch ( m ) - { - case FL_PUSH: - { - int r = 0; - if ( test_press( FL_BUTTON1 ) ) - { - /* don't let Module::handle eat our click */ - r = Fl_Group::handle( m ); - } - return Module::handle( m ) || r; - } - } - - return Module::handle( m ); -} - - - -/**********/ -/* Engine */ -/**********/ - - -void -Meter_Module::process ( nframes_t nframes ) -{ - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - { -// float dB = 20 * log10( get_peak_sample( (float*)audio_input[i].buffer(), nframes ) / 2.0f ); - float dB = 20 * log10( buffer_get_peak( (sample_t*) audio_input[i].buffer(), nframes ) ); - - ((float*)control_output[0].buffer())[i] = dB; - if (dB > control_value[i]) - control_value[i] = dB; - } -} diff --git a/mixer/src/Meter_Module.H b/mixer/src/Meter_Module.H deleted file mode 100644 index 2b3e72b..0000000 --- a/mixer/src/Meter_Module.H +++ /dev/null @@ -1,51 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" - -class Fl_Scalepack; - -class Meter_Module : public Module -{ - Fl_Scalepack *dpm_pack; - - volatile float *control_value; - -public: - - Meter_Module ( ); - virtual ~Meter_Module ( ); - - const char *name ( void ) const { return "Meter"; } - - int can_support_inputs ( int n ) { return n > 0 ? n : -1; } - bool configure_inputs ( int n ); - - LOG_CREATE_FUNC( Meter_Module ); - - virtual void update ( void ); - -protected: - - virtual int handle ( int m ); - virtual void process ( nframes_t nframes ); - virtual void draw ( void ) { draw_box(x(),y(),w(),h()); } -}; diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C deleted file mode 100644 index 0969a9e..0000000 --- a/mixer/src/Mixer.C +++ /dev/null @@ -1,1310 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* This is the main mixer group. It contains and manages Mixer_Strips. */ -#include "const.h" - -#include "Mixer.H" -#include "Mixer_Strip.H" - -#include -#include -#include -#include -#include -#include -#include -#include "Project.H" -#include -#include -#include -#include -#include -#include -#include "file.h" -#include "Group.H" -#include -#include "debug.h" -#include -#include - -#include "OSC/Endpoint.H" -#include - -#include "Controller_Module.H" - -const double FEEDBACK_UPDATE_FREQ = 1.0f; - -extern char *user_config_dir; -extern char *instance_name; - -#include "debug.h" -#include "string_util.h" - -#include "NSM.H" -#include -#include "Chain.H" - -extern NSM_Client *nsm; - -Spatialization_Console *Mixer::spatialization_console = 0; - - - -void -Mixer::show_tooltip ( const char *s ) -{ - mixer->_status->label( s ); -} - -void -Mixer::hide_tooltip ( void ) -{ - mixer->_status->label( 0 ); -} - - -/************************/ -/* OSC Message Handlers */ -/************************/ - -#undef OSC_REPLY_OK -#undef OSC_REPLY_ERR -#undef OSC_REPLY - -#define OSC_REPLY_OK() ((OSC::Endpoint*)user_data)->send( lo_message_get_source( msg ), path, 0, "OK" ) -#define OSC_REPLY( value ) ((OSC::Endpoint*)user_data)->send( lo_message_get_source( msg ), path, value ) -#define OSC_REPLY_ERR(errcode, value) ((OSC::Endpoint*)user_data)->send( lo_message_get_source( msg ), path,errcode, value ) -#define OSC_ENDPOINT() ((OSC::Endpoint*)user_data) - -static int osc_add_strip ( const char *path, const char *, lo_arg **, int , lo_message msg, void *user_data ) -{ - OSC_DMSG(); - - Fl::lock(); - - ((Mixer*)(OSC_ENDPOINT())->owner)->command_add_strip(); - - Fl::unlock(); - - OSC_REPLY_OK(); - - return 0; -} - - int -Mixer::osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ) -{ - mixer->handle_hello( msg ); - return 0; -} - - -void -Mixer::handle_hello ( lo_message msg ) -{ - int argc = lo_message_get_argc( msg ); - lo_arg **argv = lo_message_get_argv( msg ); - - if ( argc >= 4 ) - { - const char *url = &argv[0]->s; - const char *name = &argv[1]->s; - const char *version = &argv[2]->s; - const char *id = &argv[3]->s; - - MESSAGE( "Got hello from NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - - mixer->osc_endpoint->handle_hello( id, url ); - } -} - -void -Mixer::say_hello ( void ) -{ - lo_message m = lo_message_new(); - - lo_message_add( m, "sssss", - "/non/hello", - osc_endpoint->url(), - APP_NAME, - VERSION, - instance_name ); - - nsm->broadcast( m ); - - lo_message_free( m ); -} - - - - -static -Fl_Menu_Item * -find_item( Fl_Menu_ *menu, const char *path ) - { - return const_cast(menu->find_item( path )); - } - -void -Mixer::sm_active ( bool b ) -{ - sm_blinker->value( b ); - sm_blinker->tooltip( nsm->session_manager_name() ); - - if ( b ) - { - find_item( menubar, "&Project/&Open" )->deactivate(); - find_item( menubar, "&Project/&New" )->deactivate(); - } -} - - -void -Mixer::redraw_windows ( void ) -{ - window()->redraw(); - - if ( Fl::first_window() ) - for ( Fl_Window *w = Fl::first_window(); ( w = Fl::next_window( w ) ); ) - w->redraw(); -} - -void Mixer::command_new ( void ) -{ - DMESSAGE( "New project" ); - - char *default_path = read_line( user_config_dir, "default_path" ); - - char *result_path = default_path; - - char *path = new_project_chooser( &result_path ); - - if ( path ) - { - if ( ! Project::create( path, NULL ) ) - fl_alert( "Error creating project!" ); - free( path ); - } - - load_project_settings(); - - update_menu(); - - if ( result_path != default_path ) - free(default_path); - - if ( result_path ) - { - write_line( user_config_dir, "default_path", result_path ); - free( result_path ); - } -} - -void Mixer::cb_menu(Fl_Widget* o) { - Fl_Menu_Bar *menu = (Fl_Menu_Bar*)o; - -/* const Fl_Menu_Item *mi = &menu->menu()[menu->value()]; */ - - char picked[256]; - // const char *picked = menu->text(); - - menu->item_pathname( picked, sizeof( picked ) ); - - DMESSAGE( "Picked %s", picked ); - - if (! strcmp( picked, "&Project/&New") ) - { - command_new(); - } - else if (! strcmp( picked, "&Project/&Open" ) ) - { - char *path = NULL; - -// read_line( user_config_dir, "default_path", &path ); - - const char *name = fl_dir_chooser( "Open Project", path ); - - free( path ); - - mixer->hide(); - - if ( int err = Project::open( name ) ) - { - fl_alert( "Error opening project: %s", Project::errstr( err ) ); - } - - update_menu(); - - mixer->show(); - } - else if (! strcmp( picked, "&Project/&Save" ) ) - { - command_save(); - } - else if (! strcmp( picked, "&Project/&Quit") ) - { - command_quit(); - } - else if ( !strcmp( picked, "&Mixer/&Add Strip" ) ) - { - command_add_strip(); - } - else if ( !strcmp( picked, "&Mixer/Add &N Strips" ) ) - { - const char *s = fl_input( "Enter number of strips to add" ); - - if ( s ) - { - for ( int i = atoi( s ); i > 0; i-- ) - command_add_strip(); - } - } - else if ( !strcmp( picked, "&Mixer/&Import Strip" ) ) - { - const char *s = fl_file_chooser( "Export strip to filename:", "*.strip", NULL, 0 ); - - if ( s ) - { - if (! Mixer_Strip::import_strip( s ) ) - fl_alert( "%s", "Failed to import strip!" ); - } - } - else if ( ! strcmp( picked, "&Project/Se&ttings/Learn/By Strip Name" ) ) - { - Controller_Module::learn_by_number = false; - } - else if ( ! strcmp( picked, "&Project/Se&ttings/Learn/By Strip Number" ) ) - { - Controller_Module::learn_by_number = true; - } - else if ( ! strcmp( picked, "&Remote Control/Start Learning" ) ) - { - Controller_Module::learn_mode( true ); - tooltip( "Now in learn mode. Click on a highlighted control to teach it something." ); - redraw(); - } - else if ( ! strcmp( picked, "&Remote Control/Stop Learning" ) ) - { - Controller_Module::learn_mode( false ); - tooltip( "Learning complete" ); - redraw(); - } - else if ( !strcmp( picked, "&Remote Control/Send State" ) ) - { - send_feedback(); - } - else if ( ! strcmp( picked, "&Remote Control/Clear All Mappings" ) ) - { - if ( 1 == fl_choice( "This will remove all mappings, are you sure?", "No", "Yes", NULL ) ) - { - command_clear_mappings(); - } - } - else if ( !strcmp( picked, "&Mixer/Paste" ) ) - { - Fl::paste(*this); - } - else if (! strcmp( picked, "&Project/Se&ttings/&Rows/One") ) - { - rows( 1 ); - } - else if (! strcmp( picked, "&Project/Se&ttings/&Rows/Two") ) - { - rows( 2 ); - } - else if (! strcmp( picked, "&Project/Se&ttings/&Rows/Three") ) - { - rows( 3 ); - } - else if (! strcmp( picked, "&Mixer/&Spatialization Console") ) - { - if ( ! spatialization_console ) - { - Spatialization_Console *o = new Spatialization_Console(); - spatialization_console = o; - } - - if ( ! menu->mvalue()->value() ) - spatialization_console->hide(); - else - spatialization_console->show(); - } - else if (! strcmp( picked, "&Project/Se&ttings/Make Default") ) - { - save_default_project_settings(); - } - else if (! strcmp( picked, "&View/&Theme") ) - { - fl_theme_chooser(); - } - else if ( ! strcmp( picked, "&Mixer/Swap &Fader//Signal View" ) ) - { - command_toggle_fader_view(); - } - else if ( ! strcmp( picked, "&Help/&About" ) ) - { - About_Dialog ab( PIXMAP_PATH "/non-mixer/icon-256x256.png" ); - - ab.logo_box->label( VERSION ); - - ab.title->label( "Non Mixer" ); - - ab.copyright->label( "Copyright (C) 2008-2013 Jonathan Moore Liles" ); - ab.credits->label( - "Non Mixer was written from scratch by\n" - "Jonathan Moore Liles for his own use\n" - "(see the manual).\n" - "\n" - "Nobody planned. Nobody helped.\n" - "You can help now by donating time, money,\n" - "and/or replacing the rest of Linux Audio\n" - "with fast, light, reliable alternatives.\n" ); - - ab.website_url->label( "http://non.tuxfamily.org" ); - - ab.run(); - } - else if ( !strcmp( picked, "&Help/&Manual" )) - { - char *pat; - - asprintf( &pat, "file://%s.html", DOCUMENT_PATH "/non-mixer/MANUAL" ); - - open_url( pat ); - - free( pat ); - } -} - -void Mixer::cb_menu(Fl_Widget* o, void* v) { - ((Mixer*)(v))->cb_menu(o); -} - -void Mixer::update_frequency ( float v ) -{ - _update_interval = 1.0f / v; - - Fl::remove_timeout( &Mixer::update_cb, this ); - Fl::add_timeout( _update_interval, &Mixer::update_cb, this ); -} - -void -Mixer::update_cb ( void *v ) -{ - ((Mixer*)v)->update_cb(); -} - -void -Mixer::update_cb ( void ) -{ - Fl::repeat_timeout( _update_interval, &Mixer::update_cb, this ); - - if ( active_r() && visible_r() ) - { - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - ((Mixer_Strip*)mixer_strips->child(i))->update(); - } - } -} - - -static void -progress_cb ( int p, void *v ) -{ - static int oldp = 0; - - if ( p != oldp ) - { - oldp = p; - if ( nsm ) - { - nsm->progress( p / 100.0f ); - } - Fl::check(); - } -} - -void -Mixer::save_default_project_settings ( void ) -{ - char path[256]; - snprintf( path, sizeof( path ), "%s/%s", user_config_dir, ".default_project_settings" ); - - ((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Project/Se&ttings" ), path ); -} - -void -Mixer::load_default_project_settings ( void ) -{ - char path[256]; - snprintf( path, sizeof( path ), "%s/%s", user_config_dir, ".default_project_settings" ); - - ((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Project/Se&ttings" ), path ); -} - -void -Mixer::reset_project_settings ( void ) -{ - rows(1); - - load_default_project_settings(); -} - -void -Mixer::save_project_settings ( void ) -{ - if ( ! Project::open() ) - return; - - ((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Project/Se&ttings" ), "options" ); -} - -void -Mixer::load_project_settings ( void ) -{ - reset_project_settings(); - -// if ( Project::open() ) - ((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Project/Se&ttings" ), "options" ); - - update_menu(); -} - -Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) : - Fl_Group( X, Y, W, H, L ) -{ - Loggable::dirty_callback( &Mixer::handle_dirty, this ); - Loggable::progress_callback( progress_cb, NULL ); - - Fl_Tooltip::hoverdelay( 0 ); - Fl_Tooltip::delay( 0 ); - fl_show_tooltip = &Mixer::show_tooltip; - fl_hide_tooltip = &Mixer::hide_tooltip; - /* Fl_Tooltip::size( 11 ); */ - /* Fl_Tooltip::textcolor( FL_FOREGROUND_COLOR ); */ - /* Fl_Tooltip::color( fl_color_add_alpha( FL_DARK1, 0 ) ); */ -// fl_tooltip_docked = 1; - -// _groups.resize(16); - - _rows = 1; - _strip_height = 0; - box( FL_FLAT_BOX ); - labelsize( 96 ); - { Fl_Group *o = new Fl_Group( X, Y, W, 24 ); - - { Fl_Menu_Bar *o = menubar = new Fl_Menu_Bar( X, Y, W, 24 ); - o->add( "&Project/&New" ); - o->add( "&Project/&Open" ); - o->add( "&Project/Se&ttings/&Rows/One", '1', 0, 0, FL_MENU_RADIO | FL_MENU_VALUE ); - o->add( "&Project/Se&ttings/&Rows/Two", '2', 0, 0, FL_MENU_RADIO ); - o->add( "&Project/Se&ttings/&Rows/Three", '3', 0, 0, FL_MENU_RADIO ); - o->add( "&Project/Se&ttings/Learn/By Strip Number", 0, 0, 0, FL_MENU_RADIO ); - o->add( "&Project/Se&ttings/Learn/By Strip Name", 0, 0, 0, FL_MENU_RADIO | FL_MENU_VALUE ); - o->add( "&Project/Se&ttings/Make Default", 0,0,0); - o->add( "&Project/&Save", FL_CTRL + 's', 0, 0 ); - o->add( "&Project/&Quit", FL_CTRL + 'q', 0, 0 ); - o->add( "&Mixer/&Add Strip", 'a', 0, 0 ); - o->add( "&Mixer/Add &N Strips" ); - o->add( "&Mixer/&Import Strip" ); - o->add( "&Mixer/Paste", FL_CTRL + 'v', 0, 0 ); - o->add( "&Mixer/&Spatialization Console", FL_F + 8, 0, 0, FL_MENU_TOGGLE ); - o->add( "&Mixer/Swap &Fader//Signal View", FL_ALT + 'f', 0, 0, FL_MENU_TOGGLE ); -// o->add( "&Mixer/&Signal View", FL_ALT + 's', 0, 0, FL_MENU_TOGGLE ); - o->add( "&Remote Control/Start Learning", FL_F + 9, 0, 0 ); - o->add( "&Remote Control/Stop Learning", FL_F + 10, 0, 0 ); - o->add( "&Remote Control/Send State" ); - o->add( "&Remote Control/Clear All Mappings", 0, 0, 0 ); - o->add( "&View/&Theme", 0, 0, 0 ); - o->add( "&Help/&Manual" ); - o->add( "&Help/&About" ); - o->callback( cb_menu, this ); - } - { Fl_Box *o = project_name = new Fl_Box( X + 150, Y, W, 24 ); - o->labelfont( FL_HELVETICA_ITALIC ); - o->label( 0 ); - o->align( FL_ALIGN_INSIDE | FL_ALIGN_CENTER ); - o->labeltype( FL_SHADOW_LABEL ); - Fl_Group::current()->resizable( o ); - } - { sm_blinker = new Fl_Button( ( X + W) - 37, Y + 4, 35, 15, "SM"); - sm_blinker->box(FL_ROUNDED_BOX); - sm_blinker->down_box(FL_ROUNDED_BOX); - sm_blinker->color(FL_DARK2); - sm_blinker->selection_color((Fl_Color)93); - sm_blinker->labeltype(FL_NORMAL_LABEL); - sm_blinker->labelfont(3); - sm_blinker->labelsize(14); - sm_blinker->labelcolor(FL_DARK3); - sm_blinker->align(Fl_Align(FL_ALIGN_CENTER)); - sm_blinker->when(FL_WHEN_RELEASE); - sm_blinker->deactivate(); - - } // Fl_Blink_Button* sm_blinker - o->end(); - } - { Fl_Scroll *o = scroll = new Fl_Scroll( X, Y + 24, W, H - ( 100 ) ); - o->box( FL_FLAT_BOX ); -// o->type( Fl_Scroll::HORIZONTAL_ALWAYS ); -// o->box( Fl_Scroll::BOTH ); - { - Fl_Flowpack *o = mixer_strips = new Fl_Flowpack( X, Y + 24, W, H - ( 18*2 + 24 )); -// label( "Non-Mixer" ); - align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE) ); - o->flow( false ); - o->box( FL_FLAT_BOX ); - o->type( Fl_Pack::HORIZONTAL ); - o->hspacing( 2 ); - o->vspacing( 2 ); - o->end(); - Fl_Group::current()->resizable( o ); - } - o->end(); - Fl_Group::current()->resizable( o ); - } - { Fl_Box *o = _status = new Fl_Box( X, Y + H - 18, W, 18 ); - o->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); - o->labelsize( 10 ); - o->box( FL_FLAT_BOX ); - o->color( FL_DARK1 ); - } - end(); - - resize( X,Y,W,H ); - - update_frequency( 15 ); - - Fl::add_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, this ); - - update_menu(); - - load_options(); -} - -/* translate message addressed to strip number to appropriate strip */ -int -Mixer::osc_strip_by_number ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) -{ - int n; - char *rem; - char *client_name; - - OSC::Endpoint *ep = (OSC::Endpoint*)user_data; - - if ( 3 != sscanf( path, "%m[^/]/strip#/%d/%m[^\n]", &client_name, &n, &rem ) ) - return -1; - - Mixer_Strip *o = mixer->track_by_number( n ); - - if ( ! o ) - { - DMESSAGE( "No strip by number %i", n ); - return 0; - } - - char *new_path; - - asprintf( &new_path, "%s/strip/%s/%s", client_name, o->name(), rem ); - - free( rem ); - - lo_send_message( ep->address(), new_path, msg ); - - free( new_path ); - - return 0; -} - -void -Mixer::load_translations ( void ) -{ - FILE *fp = fopen( "mappings", "r" ); - - if ( ! fp ) - { - WARNING( "Error opening mappings file for reading" ); - return; - } - - char *to; - char *from; - - while ( 2 == fscanf( fp, "%m[^|> ] |> %m[^ \n]\n", &from, &to ) ) - { - osc_endpoint->add_translation( from, to ); - free(from); - free(to); - } - - fclose( fp ); -} - -void -Mixer::save_translations ( void ) -{ - FILE *fp = fopen( "mappings", "w" ); - - if ( ! fp ) - { - WARNING( "Error opening mappings file for writing" ); - return; - } - - for ( int i = 0; i < osc_endpoint->ntranslations(); i++ ) - { - const char *to; - const char *from; - - if ( osc_endpoint->get_translation( i, &to, &from ) ) - { - fprintf( fp, "%s |> %s\n", to, from ); - } - } - - fclose( fp ); -} - -int -Mixer::init_osc ( const char *osc_port ) -{ - osc_endpoint = new OSC::Endpoint(); - - if ( int r = osc_endpoint->init( LO_UDP, osc_port ) ) - return r; - - osc_endpoint->owner = this; - - printf( "OSC=%s\n", osc_endpoint->url() ); - - osc_endpoint->add_method( "/non/hello", "ssss", &Mixer::osc_non_hello, osc_endpoint, "" ); - -// - osc_endpoint->add_method( "/non/mixer/add_strip", "", osc_add_strip, osc_endpoint, "" ); - - osc_endpoint->start(); - - osc_endpoint->add_method( NULL, NULL, osc_strip_by_number, osc_endpoint, ""); - - return 0; -} - - -Mixer::~Mixer ( ) -{ - DMESSAGE( "Destroying mixer" ); - - save_options(); - - Fl::remove_timeout( &Mixer::update_cb, this ); - - Fl::remove_timeout( &Mixer::send_feedback_cb, this ); - -/* FIXME: teardown */ - mixer_strips->clear(); -} - -void -Mixer::add_group ( Group *g ) -{ - groups.push_back( g ); - - for ( int i = mixer_strips->children(); i--; ) - ((Mixer_Strip*)mixer_strips->child(i))->update_group_choice(); -} - -void -Mixer::remove_group ( Group *g ) -{ - groups.remove(g); - - for ( int i = mixer_strips->children(); i--; ) - ((Mixer_Strip*)mixer_strips->child(i))->update_group_choice(); -} - -void Mixer::resize ( int X, int Y, int W, int H ) -{ - Fl_Group::resize( X, Y, W, H ); - - scroll->resize( X, Y + 24, W, H - 24 - 18 ); - - mixer_strips->resize( X, Y + 24, W, H - (18*2) - 24 ); - - rows( _rows ); -} - -void Mixer::add ( Mixer_Strip *ms ) -{ - MESSAGE( "Add mixer strip \"%s\"", ms->name() ); - - mixer_strips->add( ms ); - - ms->size( ms->w(), _strip_height ); - ms->redraw(); - ms->take_focus(); -} - -int -Mixer::find_strip ( const Mixer_Strip *m ) const -{ - return mixer_strips->find( m ); -} - -void -Mixer::quit ( void ) -{ - /* TODO: save project? */ - - while ( Fl::first_window() ) Fl::first_window()->hide(); -} - - -void -Mixer::insert ( Mixer_Strip *ms, Mixer_Strip *before ) -{ -// mixer_strips->remove( ms ); - mixer_strips->insert( *ms, before ); -// scroll->redraw(); -} -void -Mixer::insert ( Mixer_Strip *ms, int i ) -{ - Mixer_Strip *before = (Mixer_Strip*)mixer_strips->child( i ); - - insert( ms, before); -} - -void -Mixer::move_left ( Mixer_Strip *ms ) -{ - int i = mixer_strips->find( ms ); - - if ( i > 0 ) - insert( ms, i - 1 ); - - /* FIXME: do better */ - mixer_strips->redraw(); -} - -void -Mixer::move_right ( Mixer_Strip *ms ) -{ - int i = mixer_strips->find( ms ); - - if ( i < mixer_strips->children() - 1 ) - insert( ms, i + 2 ); - - /* FIXME: do better */ - mixer_strips->redraw(); -} - -void Mixer::remove ( Mixer_Strip *ms ) -{ - MESSAGE( "Remove mixer strip \"%s\"", ms->name() ); - - mixer_strips->remove( ms ); - - ms->group()->remove( ms ); - - if ( parent() ) - parent()->redraw(); -} - - -Mixer_Strip * -Mixer::event_inside ( void ) -{ - for ( int i = mixer_strips->children(); i--; ) - if ( Fl::event_inside( mixer_strips->child(i) ) ) - return (Mixer_Strip*)mixer_strips->child(i); - - return NULL; -} - -bool -Mixer::contains ( Mixer_Strip *ms ) -{ - return ms->parent() == mixer_strips; -} - -/* set the ideal number of rows... All may not actually fit. */ -void -Mixer::rows ( int ideal_rows ) -{ - int sh = 0; - - int actual_rows = 1; - - /* calculate how many rows will actually fit */ - int can_fit = scroll->h() / ( Mixer_Strip::min_h() ); - - actual_rows = can_fit > 0 ? can_fit : 1; - - if ( actual_rows > ideal_rows ) - actual_rows = ideal_rows; - - /* calculate strip height */ - if ( actual_rows > 1 ) - { - sh = ( scroll->h() / (float)actual_rows ) - ( mixer_strips->vspacing() * ( actual_rows - 2 )); - mixer_strips->flow(true); - } - else - actual_rows = 1; - - if ( 1 == actual_rows ) - { - sh = (scroll->h() - 18); - mixer_strips->flow( false ); - } - - int tw = 0; - - for ( int i = 0; i < mixer_strips->children(); ++i ) - { - Mixer_Strip *t = (Mixer_Strip*)mixer_strips->child( i ); - - t->size( t->w(), sh ); - - tw += t->w() + mixer_strips->hspacing(); - } - - if ( actual_rows > 1 ) - mixer_strips->size( scroll->w() - 18, mixer_strips->h() ); - else - mixer_strips->size( tw, sh ); - - _rows = ideal_rows; - - if ( _strip_height != sh ); - { - mixer_strips->redraw(); - scroll->redraw(); - _strip_height = sh; - } -} - -int -Mixer::nstrips ( void ) const -{ - return mixer_strips->children(); -} - -/** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */ -Mixer_Strip * -Mixer::track_by_name ( const char *name ) -{ - for ( int i = mixer_strips->children(); i-- ; ) - { - Mixer_Strip *t = (Mixer_Strip*)mixer_strips->child( i ); - - if ( ! strcmp( name, t->name() ) ) - return t; - } - - return NULL; -} -/** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */ -Mixer_Strip * -Mixer::track_by_number ( int n ) -{ - if ( n < 0 || n >= mixer_strips->children() ) - return NULL; - - return (Mixer_Strip*)mixer_strips->child(n); -} - -/** return a malloc'd string representing a unique name for a new track */ -char * -Mixer::get_unique_track_name ( const char *name ) -{ - char pat[256]; - - strcpy( pat, name ); - - for ( int i = 1; track_by_name( pat ); ++i ) - snprintf( pat, sizeof( pat ), "%s.%d", name, i ); - - return strdup( pat ); -} - -Group * -Mixer::group_by_name ( const char *name ) -{ - for ( std::list::iterator i = groups.begin(); - i != groups.end(); - i++ ) - if ( !strcmp( (*i)->name(), name )) - return *i; - - return NULL; -} - -char * -Mixer::get_unique_group_name ( const char *name ) -{ - char pat[256]; - - strcpy( pat, name ); - - for ( int i = 1; group_by_name( pat ); ++i ) - snprintf( pat, sizeof( pat ), "%s.%d", name, i ); - - return strdup( pat ); -} - -void -Mixer::handle_dirty ( int d, void *v ) -{ - //Mixer *m = (Mixer*)v; - if ( !nsm ) - return; - - if ( d == 1 ) - nsm->is_dirty(); - else if ( d == 0 ) - nsm->is_clean(); -} - - -void -Mixer::snapshot ( void ) -{ - if ( spatialization_console ) - spatialization_console->log_create(); - - for ( std::list::iterator i = groups.begin(); i != groups.end(); ++i ) - (*i)->log_create(); - - for ( int i = 0; i < mixer_strips->children(); ++i ) - ((Mixer_Strip*)mixer_strips->child( i ))->log_children(); -} - - -void -Mixer::new_strip ( void ) -{ - add( new Mixer_Strip( get_unique_track_name( "Unnamed" ) ) ); -} - -bool -Mixer::save ( void ) -{ - MESSAGE( "Saving state" ); - Loggable::snapshot_callback( &Mixer::snapshot, this ); - Loggable::snapshot( "snapshot" ); - - save_translations(); - return true; -} - -static const char options_filename[] = "options"; - -void -Mixer::load_options ( void ) -{ -// save options - - /* char *path; */ - /* asprintf( &path, "%s/options", user_config_dir ); */ - /* ((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Options" ), path ); */ - /* free( path ); */ -} - -void -Mixer::save_options ( void ) -{ - /* char *path; */ - /* asprintf( &path, "%s/%s", user_config_dir, options_filename ); */ - /* ((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Options" ), path ); */ - /* free( path ); */ -} - -void -Mixer::update_menu ( void ) -{ - project_name->label( Project::name() ); - - const_cast(menubar->find_item( "&Mixer/&Spatialization Console" )) - ->flags = FL_MENU_TOGGLE | ( ( spatialization_console && spatialization_console->shown() ) ? FL_MENU_VALUE : 0 ); -} - -void -Mixer::send_feedback_cb ( void *v ) -{ - Mixer *m = (Mixer*)v; - - m->send_feedback(); - - Fl::repeat_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, v ); -} - -/** unconditionally send feedback to all mapped controls. This is - * useful for updating the state of an external controller. */ -void -Mixer::send_feedback ( void ) -{ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - ((Mixer_Strip*)mixer_strips->child(i))->send_feedback(); - } -} - - - -int -Mixer::handle ( int m ) -{ - - if ( Fl_Group::handle( m ) ) - return 1; - - switch ( m ) - { - case FL_PASTE: - { - if ( ! Fl::event_inside( this ) ) - return 0; - - const char *text = Fl::event_text(); - - char *file; - - if ( ! sscanf( text, "file://%m[^\r\n]\n", &file ) ) - { - WARNING( "invalid drop \"%s\"\n", text ); - return 0; - } - - unescape_url( file ); - - printf( "pasted file \"%s\"\n", file ); - - if (! Mixer_Strip::import_strip( file ) ) - fl_alert( "%s", "Failed to import strip!" ); - - return 1; - } - } - - return 0; -} - -#include - -std::list -Mixer::get_auto_connect_targets ( void ) -{ - std::list sl; - std::list rl; - - for ( int i = mixer_strips->children(); i--; ) - { - ((Mixer_Strip*)mixer_strips->child(i))->get_output_ports(sl); - } - - for ( std::list::iterator i = sl.begin(); i != sl.end(); i++ ) - { - char *s = strdup( i->c_str() ); - - *rindex( s, '/' ) = 0; - - if ( !index( s, '/' ) ) - { - char *o; - asprintf( &o, "%s/mains", s ); - free(s); - s = o; - } - - if ( std::find( rl.begin(), rl.end(), s ) == rl.end() ) - { - rl.push_back( s ); - } - - free(s); - } - - return rl; -} - -void -Mixer::auto_connect ( void ) -{ - if ( Project::is_opening() ) - /* it's more efficient to do this once at the end rather than as we go. */ - return; - - DMESSAGE("Full auto-connect cycle" ); - - /* give strips with group affinity the first shot */ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i)); - - if ( s->has_group_affinity() ) - s->auto_connect_outputs(); - } - - /* now do that catch-alls, first one wins! */ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i)); - - if ( ! s->has_group_affinity() ) - s->auto_connect_outputs(); - } -} - -void -Mixer::maybe_auto_connect_output ( Module::Port *p ) -{ - if ( Project::is_opening() ) - /* it's more efficient to do this once at the end rather than as we go. */ - return; - -// DMESSAGE( "Single output auto connect cycle" ); - - /* give strips with group affinity the first shot */ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i)); - - if ( s->has_group_affinity() ) - if ( s->maybe_auto_connect_output( p ) ) - return; - } - - /* now do that catch-alls, first one wins! */ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i)); - - if ( ! s->has_group_affinity() ) - if ( s->maybe_auto_connect_output( p ) ) - return; - } -} -/************/ -/* Commands */ -/************/ - -void -Mixer::command_toggle_fader_view ( void ) -{ - for ( int i = 0; i < mixer_strips->children(); i++ ) - { - Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i)); - s->command_toggle_fader_view(); - } -} - -void -Mixer::command_clear_mappings ( void ) -{ - osc_endpoint->clear_translations(); -} - -bool -Mixer::command_save ( void ) -{ - if ( ! Project::open() ) - { - command_new(); - update_menu(); - } - - save_project_settings(); - - return Project::save(); -} - -bool -Mixer::command_load ( const char *path, const char *display_name ) -{ - mixer->deactivate(); - - Project::close(); - - char *pwd = (char*)malloc( PATH_MAX + 1 ); - getcwd( pwd, PATH_MAX ); - chdir( path ); - load_project_settings(); - chdir( pwd ); - free( pwd ); - - if ( Project::open( path ) ) - { - // fl_alert( "Error opening project specified on commandline: %s", Project::errstr( err ) ); - return false; - } - - if ( display_name ) - Project::name( display_name ); - - load_translations(); - - update_menu(); - - auto_connect(); - - mixer->activate(); - - return true; -} - -bool -Mixer::command_new ( const char *path, const char *display_name ) -{ - if ( ! Project::create( path, "" ) ) - return false; - - if ( display_name ) - Project::name( display_name ); - - load_project_settings(); - - update_menu(); - - return true; -// fl_alert( "Error creating project!" ); -} - -void -Mixer::command_quit ( void ) -{ - if ( Loggable::dirty() ) - { - int i = fl_choice( "There have been changes since the last save. Quitting now will discard them", "Discard", "Cancel", NULL ); - - if ( i != 0 ) - return; - } - - quit(); -} - -/* */ - -void -Mixer::command_add_strip ( void ) -{ - new_strip(); -} diff --git a/mixer/src/Mixer.H b/mixer/src/Mixer.H deleted file mode 100644 index c86109b..0000000 --- a/mixer/src/Mixer.H +++ /dev/null @@ -1,176 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include -#include "Mixer_Strip.H" - -#include "Thread.H" - -class Fl_Blink_Button; -class Fl_Flowpack; -class Fl_Menu_Bar; -class Spatialization_Console; -namespace OSC { class Endpoint; } -#include -class Group; - -class Mixer : public Fl_Group -{ - -public: - - OSC::Endpoint *osc_endpoint; - Fl_Button *sm_blinker; - -private: - - float _update_interval; - - static void show_tooltip ( const char *s ); - static void hide_tooltip ( void ); - - int _rows; - int _strip_height; - - Fl_Color system_colors[3]; - - Mixer_Strip* track_by_name ( const char *name ); - - void snapshot ( void ); - static void snapshot ( void *v ) { ((Mixer*)v)->snapshot(); } - - void cb_menu(Fl_Widget*); - static void cb_menu(Fl_Widget*, void*); - - Fl_Menu_Bar *menubar; - Fl_Scroll *scroll; - Fl_Pack *pack; - Fl_Box *project_name; - Fl_Box *_status; - - Fl_Flowpack *mixer_strips; - - void load_options ( void ); - void save_options ( void ); - void save_translations ( void ); - void load_translations ( void ); - - static void send_feedback_cb ( void *v ); - void send_feedback ( void ); - void redraw_windows ( void ); - - static void handle_dirty ( int, void *v ); - - static int osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ); - static int osc_strip_by_number ( const char *, const char *, lo_arg **, int , lo_message msg, void * ); - - static void update_cb ( void * ); - void update_cb ( void ); - - -public: - - void auto_connect ( void ); - void maybe_auto_connect_output ( Module::Port *p ); - std::list get_auto_connect_targets ( void ); - Group * group_by_name ( const char * name ); - char *get_unique_group_name ( const char *name ); - - std::list groups; - Group *group ( int n ); - void add_group ( Group *g ); - void remove_group ( Group *g ); - - void update_menu ( void ); - - static Spatialization_Console *spatialization_console; - - int nstrips ( void ) const; - Mixer_Strip* track_by_number ( int n ); - - void update_frequency ( float f ); - - void status ( const char *s ) { - if ( s ) _status->copy_label( s ); - else _status->label(0); - _status->redraw(); } - - virtual int handle ( int m ); - - char * get_unique_track_name ( const char *name ); - - int min_h ( void ) const { return Mixer_Strip::min_h() + (18 * 2); } - - void rows ( int n ); - virtual void resize ( int X, int Y, int W, int H ); - - void new_strip ( void ); - void add ( Mixer_Strip *ms ); - void remove ( Mixer_Strip *ms ); - void move_left ( Mixer_Strip *ms ); - void move_right ( Mixer_Strip *ms ); - void insert ( Mixer_Strip *ms, Mixer_Strip *before ); - void insert ( Mixer_Strip *ms, int i ); - bool contains ( Mixer_Strip *ms ); - Mixer_Strip * event_inside ( void ); - int find_strip ( const Mixer_Strip *m ) const; - - bool save ( void ); - void quit ( void ); - - Mixer ( int X, int Y, int W, int H, const char *L ); - virtual ~Mixer(); - - void handle_hello ( lo_message msg ); - - void announce ( const char *nash_url, const char *process_name ); - - int init_osc ( const char* osc_port ); - - void sm_active ( bool b ); - - void say_hello ( void ); - - void save_default_project_settings ( void ); - void load_default_project_settings ( void ); - void reset_project_settings ( void ); - void save_project_settings ( void ); - void load_project_settings ( void ); - -public: - - void command_toggle_fader_view ( void ); - void command_clear_mappings ( void ); - void command_new ( void ); - bool command_save ( void ); - bool command_load ( const char *path, const char *display_name = 0 ); - bool command_new ( const char *path, const char *display_name = 0 ); - void command_quit ( void ); - - void command_add_strip ( void ); - -}; - -extern Mixer* mixer; diff --git a/mixer/src/Mixer_Strip.C b/mixer/src/Mixer_Strip.C deleted file mode 100644 index 88dffa0..0000000 --- a/mixer/src/Mixer_Strip.C +++ /dev/null @@ -1,1263 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Mixer strip control. Handles GUI and control I/O for this strip. */ - -/* A mixer strip is home to some (JACK) input ports, a fader, some - * meters, and a filter chain which can terminate either at the input - * to the spacializer or some (JACK) output ports. Since mixer strips - * are not necessarily in a 1:1 association with Non-DAW tracks, there - * is no need for busses per se. If you want to route the output of - * several strips into a single fader or filter chain, then you just - * gives those strips JACK outputs and connect them to the common - * inputs. This mechanism can also do away with the need for 'sends' - * and 'inserts'. - - */ -/* Each mixer strip comprises a fader and a panner */ - -#include "Project.H" -#include "Mixer_Strip.H" -#include -#include -#include "debug.h" - - -#include "FL/Fl_Flowpack.H" -#include -#include -#include -#include -#include "Mixer.H" - -#include "Chain.H" -#include "Gain_Module.H" -#include "Meter_Module.H" -#include "Controller_Module.H" -#include "Meter_Indicator_Module.H" -#include "debug.h" -#include "FL/focus_frame.H" -#include -#include "FL/test_press.H" -#include "FL/menu_popup.H" -#include -#include -#include "Group.H" -#include "FL/focus_frame.H" - -extern Mixer *mixer; - - - -/* add a new mixer strip (with default configuration) */ -Mixer_Strip::Mixer_Strip( const char *strip_name ) : Fl_Group( 0, 0, 120, 600 ) -{ - label( strdup( strip_name ) ); - labeltype( FL_NO_LABEL ); - - init(); - - _group = new Group(strip_name, true); - - _group->add( this ); - - chain( new Chain() ); - - _chain->initialize_with_default(); - - _chain->configure_ports(); - - color( (Fl_Color)rand() ); - -// name( strdup( strip_name ) ); - - log_create(); -} - -/* virgin strip created from journal */ -Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 ) -{ - init(); - - log_create(); -} - -Mixer_Strip::~Mixer_Strip ( ) -{ - DMESSAGE( "Destroying mixer strip" ); - -// _chain->engine()->lock(); - - log_destroy(); - - mixer->remove( this ); - - /* make sure this gets destroyed before the chain */ - fader_tab->clear(); - - delete _chain; - _chain = NULL; -} - - - -void -Mixer_Strip::get ( Log_Entry &e ) const -{ - e.add( ":name", name() ); - e.add( ":width", width_button->value() ? "wide" : "narrow" ); - e.add( ":tab", tab_button->value() ? "signal" : "fader" ); - e.add( ":color", (unsigned long)color()); - /* since the default controllers aren't logged, we have to store - * this setting as part of the mixer strip */ - e.add( ":gain_mode", gain_controller->mode() ); - e.add( ":mute_mode", mute_controller->mode() ); - if ( ! _group->single() ) - e.add( ":group", _group ); - else - e.add( ":group", (Loggable*)0 ); - e.add( ":auto_input", _auto_input ); - e.add( ":manual_connection", _manual_connection ); -} - -void -Mixer_Strip::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":name" ) ) - name( v ); - else if ( ! strcmp( s, ":width" ) ) - { - width_button->value( strcmp( v, "wide" ) == 0 ); - width_button->do_callback(); - } - else if ( ! strcmp( s, ":tab" ) ) - { - tab_button->value( strcmp( v, "signal" ) == 0 ); - tab_button->do_callback(); - } - else if ( ! strcmp( s, ":color" ) ) - { - color( (Fl_Color)atoll( v ) ); - redraw(); - } - else if ( ! strcmp( s, ":gain_mode" ) ) - { - _gain_controller_mode = atoi( v ); - } - else if ( ! strcmp( s, ":mute_mode" ) ) - { - _mute_controller_mode = atoi( v ); - } - else if ( ! strcmp( s, ":auto_input" ) ) - { - auto_input( v ); - } - else if ( ! strcmp( s, ":manual_connection" ) ) - { - manual_connection( atoi( v ) ); - } - else if ( ! strcmp( s, ":group" ) ) - { - int i; - sscanf( v, "%X", &i ); - - if ( i ) - { - Group *t = (Group*)Loggable::find( i ); - - /* Because of strip copy/paste and import, we can't assure that the group will exist by ID*/ -// assert( t ); - - group( t ); - } - else - group( 0 ); - } - } - - if ( ! _group ) - group(0); - - if ( ! mixer->contains( this ) ) - mixer->add( this ); -} - -void -Mixer_Strip::log_children ( void ) const -{ - log_create(); - - _chain->log_children(); -} - -void -Mixer_Strip::color ( Fl_Color c ) -{ - _color = c; - color_box->color( _color ); - color_box->redraw(); -} - -Fl_Color -Mixer_Strip::color ( void ) const -{ - return _color; -} - -void -Mixer_Strip::chain ( Chain *c ) -{ - if ( _chain ) - delete _chain; - - _chain = c; - - c->strip( this ); - - Fl_Group *g = signal_tab; - - c->resize( g->x(), g->y(), g->w(), g->h() ); - g->add( c ); - g->resizable( c ); - - c->labelsize( 10 ); - c->align( FL_ALIGN_TOP ); - c->color( FL_RED ); - c->configure_outputs_callback( configure_outputs, this ); - c->name( name() ); - - /* FIXME: don't hardcode this list of modules */ - spatialization_controller->chain( c ); - gain_controller->chain( c ); - mute_controller->chain( c ); - jack_input_controller->chain( c ); - meter_indicator->chain( c ); -} - - -void Mixer_Strip::cb_handle(Fl_Widget* o) { - // parent()->parent()->damage( FL_DAMAGE_ALL, x(), y(), w(), h() ); - // DMESSAGE( "Callback for %s", o->label() ); - - if ( o == tab_button ) - { - if ( tab_button->value() == 0 ) - { - fader_tab->resize( tab_group->x(), tab_group->y(), tab_group->w(), tab_group->h() ); - fader_tab->show(); - signal_tab->hide(); - tab_group->resizable( fader_tab ); - } - else - { - signal_tab->resize( tab_group->x(), tab_group->y(), tab_group->w(), tab_group->h() ); - signal_tab->show(); - fader_tab->hide(); - tab_group->resizable( signal_tab ); - } - - set_spatializer_visibility(); - } - else if ( o == close_button ) - { - if ( Fl::event_shift() || 1 == fl_choice( "Are you sure you want to remove this strip?\n\n(this action cannot be undone)", "Cancel", "Remove", NULL ) ) - command_close(); - } - else if ( o == name_field ) - { - name( name_field->value() ); - Fl::focus( this ); - } - else if ( o == width_button ) - { - if ( width_button->value() ) - size( 220, h() ); - else - size( 96, h() ); - - if ( parent() ) - parent()->parent()->redraw(); - } - else if ( o == output_connection_button ) - { - if ( output_connection_button->value() == 1 ) - o->label( output_connection_button->mvalue()->label() ); - else - o->label( NULL ); - - manual_connection( output_connection_button->value() ); - -// _manual_connection = output_connection_button->value(); - } - else if ( o == group_choice ) - { - // group(group_choice->value()); - Group *g = NULL; - - if ( group_choice->value() == group_choice->size() - 2 ) - { - /* create a new group */ - const char *s = fl_input( "Name for Group:" ); - if ( !s ) - return; - - char *n = mixer->get_unique_group_name( s ); - - g = new Group( n, false ); - - free( n ); - - mixer->add_group( g ); - } - else - { - g = (Group*)group_choice->mvalue()->user_data(); - } - - group(g); - } -} - -void Mixer_Strip::cb_handle(Fl_Widget* o, void* v) { - ((Mixer_Strip*)(v))->cb_handle(o); -} - -void -Mixer_Strip::group ( Group *g ) -{ - if ( !g && _group && _group->single() ) - return; - - if ( _group ) - { - _group->remove(this); - if ( ! _group->nstrips() ) - { - if ( ! _group->single() ) - mixer->remove_group( _group ); - - delete _group; - - _group = NULL; - } - } - - if ( ! g ) - g = new Group(name(), true); - - const Fl_Menu_Item *menu = group_choice->menu(); - - for ( unsigned int i = 0; menu[i].text; i++ ) - if ( menu[i].user_data() == g ) - group_choice->value( i ); - -// group_choice->color( (Fl_Color)n ); -// group_choice->value( n ); - - _group = g; - - g->add(this); -} - -void -Mixer_Strip::name ( const char *name ) -{ - if ( this->name() && !strcmp( name, this->name() ) ) - return; - - name = mixer->get_unique_track_name( name ); - - char *s = strdup( name ); - - if ( strlen( s ) > Chain::maximum_name_length() ) - { - s[Chain::maximum_name_length() - 1] = '\0'; - - fl_alert( "Name \"%s\" is too long, truncating to \"%s\"", name, s ); - } - - name_field->value( s ); - label( s ); - if ( _chain ) - _chain->name( s ); -} - -void -Mixer_Strip::configure_outputs ( Fl_Widget *, void *v ) -{ - ((Mixer_Strip*)v)->configure_outputs(); -} - -void -Mixer_Strip::configure_outputs ( void ) -{ - DMESSAGE( "Got signal to configure outputs" ); -} - -void -Mixer_Strip::set_spatializer_visibility ( void ) -{ - if ( fader_tab->visible() && spatialization_controller->is_controlling() ) - { - spatialization_controller->show(); - spatialization_label->show(); - } - else - { - spatialization_controller->hide(); - spatialization_label->hide(); - } -} - -/* called by the chain to let us know that a module has been added */ -void -Mixer_Strip::handle_module_added ( Module *m ) -{ - if ( m->is_default() ) - { - DMESSAGE( "Connecting controls to default module \"%s\"", m->name() ); - - /* connect default modules to their default controllers/indicators */ - if ( 0 == strcmp( m->name(), "JACK" ) && m->ninputs() == 0 ) - { - if ( !jack_input_controller->control_output[0].connected() ) - jack_input_controller->connect_to( &m->control_input[1] ); - } - else if ( 0 == strcmp( m->name(), "Gain" ) ) - { - gain_controller->connect_to( &m->control_input[0] ); - gain_controller->mode( (Controller_Module::Mode)_gain_controller_mode ); - mute_controller->connect_to( &m->control_input[1] ); - mute_controller->mode( (Controller_Module::Mode)_mute_controller_mode ); - } - else if ( 0 == strcmp( m->name(), "Meter" ) ) - { - meter_indicator->connect_to( &m->control_output[0] ); - } - } - else - { - if ( spatialization_controller->connect_spatializer_to( m ) ) - { - DMESSAGE( "Connected spatializer to module \"%s\"", m->name() ); - set_spatializer_visibility(); - } - } -} - - -/* called by the chain to let us know that a module has been removed */ -void -Mixer_Strip::handle_module_removed ( Module *m ) -{ - if ( spatialization_controller->control_output[0].connected() && - spatialization_controller->control_output[0].connected_port()->module() == m ) - { - set_spatializer_visibility(); - DMESSAGE( "Module \"%s\" disconnected from spatialization controller", m->label() ); - } -} - -/* update GUI with values from RT thread */ -void -Mixer_Strip::update ( void ) -{ - THREAD_ASSERT( UI ); - - meter_indicator->update(); - gain_controller->update(); - mute_controller->update(); - - if ( _chain ) - { - _chain->update(); - } - if ( group() ) - { - if ( ( _dsp_load_index++ % 10 ) == 0 ) - { - float l = group()->dsp_load(); - - dsp_load_progress->value( l ); - - { - char pat[20]; - snprintf( pat, sizeof(pat), "%.1f%%", l * 100.0f ); - dsp_load_progress->copy_tooltip( pat ); - } - - if ( l <= 0.15f ) - dsp_load_progress->color2( fl_rgb_color( 127,127,127 ) ); - else - dsp_load_progress->color2( FL_RED ); - } - } -} - -void -Mixer_Strip::init ( ) -{ - selection_color( FL_YELLOW ); - _manual_connection = 0; - _auto_input = 0; - _mute_controller_mode = 0; - _gain_controller_mode = 0; - _chain = 0; - _group = 0; - - _dsp_load_index = 0; - - box( FL_FLAT_BOX ); - labeltype( FL_NO_LABEL ); - - Fl_Group::color( FL_BACKGROUND_COLOR ); - - set_visible_focus(); - - { Fl_Scalepack *o = new Fl_Scalepack( 2, 2, 116, 595 ); - o->type( FL_VERTICAL ); - o->spacing( 2 ); - - { Fl_Box *o = color_box = new Fl_Box( 0,0, 25, 10 ); - o->box(FL_FLAT_BOX); - o->tooltip( "Drag and drop to move strip" ); - } - - { Fl_Pack *o = new Fl_Pack( 2, 2, 114, 100 ); - o->type( Fl_Pack::VERTICAL ); - o->spacing( 2 ); - { - Fl_Sometimes_Input *o = new Fl_Sometimes_Input( 2, 2, 144, 15 ); - name_field = o; - - o->up_box( FL_NO_BOX ); - o->box( FL_FLAT_BOX ); - o->selection_color( FL_BLACK ); - o->labeltype( FL_NO_LABEL ); - o->labelcolor( FL_GRAY0 ); - o->textcolor( FL_FOREGROUND_COLOR ); - o->textsize( 12 ); - o->value( name() ); - o->callback( cb_handle, (void*)this ); - } - { Fl_Scalepack *o = new Fl_Scalepack( 7, 143, 110, 18 ); - o->type( Fl_Pack::HORIZONTAL ); - - { Fl_Flip_Button* o = width_button = new Fl_Flip_Button(61, 183, 45, 22, "[]/[-]"); - o->type(1); - o->tooltip( "Switch between wide and narrow views" ); - o->labelfont( FL_COURIER_BOLD ); - o->labelsize(10); - o->callback( ((Fl_Callback*)cb_handle), this ); - o->when(FL_WHEN_RELEASE); - } - - { Fl_Button* o = close_button = new Fl_Button(7, 143, 35, 25, "X"); - o->tooltip( "Remove strip" ); - o->type(0); - o->labelfont( FL_COURIER_BOLD ); - o->selection_color( FL_RED ); - o->labelsize(10); - o->when( FL_WHEN_RELEASE ); - o->callback( ((Fl_Callback*)cb_handle), this ); - } // Fl_Button* o - - o->end(); - } // Fl_Group* o - { Fl_Progress* o = dsp_load_progress = new Fl_Progress(61, 183, 45, 14, "group dsp"); - o->box(FL_BORDER_BOX); - o->type(FL_HORIZONTAL); - o->labelsize( 9 ); - o->minimum( 0 ); -// o->maximum( 0.25f ); - o->maximum( 1 ); - o->color(fl_rgb_color( 10,10,10 ) ); - o->color2(FL_CYAN); - } - { Fl_Choice* o = group_choice = new Fl_Choice(61, 183, 45, 22); - o->tooltip( "Create or assign group" ); - o->labeltype(FL_NO_LABEL); - o->labelsize(10); - o->textsize(10); - o->add("---"); - o->value(0); - o->callback( ((Fl_Callback*)cb_handle), this ); - } - { Fl_Scalepack *o = new Fl_Scalepack( 0,0, 45, 22 ); - o->type( FL_HORIZONTAL ); - { Fl_Flip_Button* o = tab_button = new Fl_Flip_Button(61, 183, 45, 22, "Fadr/Signl"); - o->tooltip( "Switch between fader and signal views" ); - o->type(1); - o->labelsize( 10 ); - o->callback( ((Fl_Callback*)cb_handle), this ); - o->when(FL_WHEN_RELEASE); - } - { Controller_Module *o = mute_controller = new Controller_Module( true ); - o->pad( false ); - o->size( 45, 22 ); - } - o->end(); - } - o->end(); - } - -/* { Fl_Scalepack *o = new Fl_Scalepack( 2, 103, 114, 490 ); */ -/* o->type( FL_VERTICAL ); */ -// o->box( FL_FLAT_BOX ); -// o->color( FL_BACKGROUND_COLOR ); - { Fl_Group *o = tab_group = new Fl_Group( 2, 116, 105, 330 ); - o->box( FL_NO_BOX ); - { Fl_Group *o = fader_tab = new Fl_Group( 2, 116, 105, 330, "Fader" ); - o->box( FL_NO_BOX ); - o->labeltype( FL_NO_LABEL ); - { Fl_Pack *o = new Fl_Pack( 2, 116, 105, 15 ); - o->type( FL_VERTICAL ); - { - Controller_Module *m = jack_input_controller = new Controller_Module( true ); - m->labeltype( FL_NO_LABEL ); - m->chain( _chain ); - m->pad( false ); - m->size( 105, 15 ); - } - o->resizable(0); - o->end(); - } - { Fl_Scalepack* o = new Fl_Scalepack(2, 135, 105, 311 ); - // o->box( FL_BORDER_BOX ); -// o->color( FL_RED ); - o->spacing( 20 ); - o->type( Fl_Scalepack::HORIZONTAL ); - { Controller_Module *o = gain_controller = new Controller_Module( true ); - o->horizontal(false); - o->clear_visible_focus(); - o->pad( false ); - o->size( 33, 100 ); - } - { Meter_Indicator_Module *o = meter_indicator = new Meter_Indicator_Module( true ); - o->disable_context_menu( true ); - o->pad( false ); - o->size( 38, 100 ); - Fl_Group::current()->resizable(o); - } - o->end(); - Fl_Group::current()->resizable(o); - } // Fl_Group* o - o->end(); - Fl_Group::current()->resizable(o); - } - { Fl_Group *o = signal_tab = new Fl_Group( 2, 116, 105, 330 ); - o->box( FL_NO_BOX ); - o->labeltype( FL_NO_LABEL ); - o->hide(); - o->end(); - } - o->end(); - Fl_Group::current()->resizable( o ); - } -/* { Fl_Pack *o = panner_pack = new Fl_Pack( 2, 465, 114, 40 ); */ -/* o->spacing( 2 ); */ -/* o->type( Fl_Pack::VERTICAL ); */ - { Fl_Box *o = spatialization_label = new Fl_Box( 0, 0, 100, 12 ); - o->align( (Fl_Align)(FL_ALIGN_BOTTOM | FL_ALIGN_INSIDE) ); - o->labelsize( 10 ); - o->hide(); - o->label( "Spatialization" ); - } - { Controller_Module *o = spatialization_controller = new Controller_Module( true ); - o->hide(); - o->label( 0 ); - o->pad( false ); - o->size( 92,92 ); - } -/* o->end(); */ -/* } */ - - { Fl_Menu_Button *o = output_connection_button = new Fl_Menu_Button( 0, 0, 10, 18 ); - o->labelsize( 9 ); - o->add("- auto -"); - o->add("- manual -"); - o->align( FL_ALIGN_CLIP ); - o->labelcolor( FL_YELLOW ); - o->callback( cb_handle, this ); - o->hide(); - } - - o->end(); - } - - end(); - - color( FL_BLACK ); - - size( 96, h() ); - - update_group_choice(); -// redraw(); - - // _chain->configure_ports(); -} - -void -Mixer_Strip::update_group_choice ( void ) -{ - Fl_Choice *o = group_choice; - - o->clear(); - o->add( "---" ); - - for ( std::list::iterator i = mixer->groups.begin(); i != mixer->groups.end(); ) - { - Group *g = *i; - - i++; - - if ( i == mixer->groups.end() ) - { - o->add( g->name(), 0, 0, (void*)g, FL_MENU_DIVIDER ); - break; - } - else - o->add( g->name(), 0, 0, (void*)g ); - } - - o->add( "New Group" ); - - const Fl_Menu_Item *menu = o->menu(); - - if ( ! group() || ( group() && group()->single() ) ) - o->value(0); - else - { - for ( unsigned int i = 0; menu[i].text; i++ ) - if ( menu[i].user_data() == group() ) - o->value( i ); - } -} - -void -Mixer_Strip::draw ( void ) -{ - /* don't bother drawing anything else, all we're doing is drawing the focus. */ -// if ( damage() & ~FL_DAMAGE_USER1 ) - Fl_Group::draw(); - - if ( focused_r( this ) ) - draw_focus_frame( x(),y(),w(),h(), Fl_Group::selection_color() ); - /* else */ - /* clear_focus_frame( x(),y(),w(),h(), FL_BACKGROUND_COLOR ); */ -} - -/*****************/ -/* Import/Export */ -/*****************/ - -void -Mixer_Strip::snapshot ( void *v ) -{ - ((Mixer_Strip*)v)->snapshot(); -} - -void -Mixer_Strip::snapshot ( void ) -{ - log_children(); -} - -bool -Mixer_Strip::export_strip ( const char *filename ) -{ - MESSAGE( "Exporting chain state" ); - Loggable::snapshot_callback( &Mixer_Strip::snapshot, this ); - Loggable::snapshot( filename ); - return true; -} - -bool -Mixer_Strip::import_strip ( const char *filename ) -{ - MESSAGE( "Importing new chain state" ); - Loggable::begin_relative_id_mode(); - int r = Loggable::replay( filename ); - Loggable::end_relative_id_mode(); - return r; -} - - - - - -void -Mixer_Strip::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[256]; - - m->item_pathname( picked, sizeof( picked ) ); - - Logger log( this ); - - if ( ! strcmp( picked, "Width/Narrow" ) ) - command_width( false ); - else if ( ! strcmp( picked, "Width/Wide" ) ) - command_width( true ); - else if ( ! strcmp( picked, "View/Fader" ) ) - command_view( false ); - else if ( ! strcmp( picked, "View/Signal" ) ) - command_view( true ); - else if ( ! strcmp( picked, "/Move Left" ) ) - command_move_left(); - else if ( ! strcmp( picked, "/Move Right" ) ) - command_move_right(); - else if ( ! strcmp( picked, "/Rename" ) ) - { - ((Fl_Sometimes_Input*)name_field)->take_focus(); - } - else if ( ! strcmp( picked, "/Copy" ) ) - { - export_strip( "clipboard.strip" ); - - char *s; - asprintf( &s, "file://%s/%s\r\n", Project::path(), "clipboard.strip" ); - - Fl::copy( s, strlen(s), 0 ); - - free(s); - } - else if ( ! strcmp( picked, "/Color" ) ) - { - unsigned char r, g, b; - - Fl::get_color( color(), r, g, b ); - - if ( fl_color_chooser( "Strip Color", r, g, b ) ) - color( fl_rgb_color( r, g, b ) ); - - redraw(); - } - else if ( !strcmp( picked, "/Export Strip" ) ) - { - char *suggested_name; - asprintf( &suggested_name, "%s.strip", name() ); - - const char *s = fl_file_chooser( "Export strip to filename:", "*.strip", suggested_name, 0 ); - - free( suggested_name ); - - if ( s ) - export_strip( s ); - - fl_message( "Strip exported." ); - } - else if ( ! strcmp( picked, "/Remove" ) ) - { - if ( Fl::event_shift() || 1 == fl_choice( "Are you sure you want to remove this strip?\n\n(this action cannot be undone)", "Cancel", "Remove", NULL ) ) - command_close(); - } - else if ( ! strcmp( picked, "/Gain" ) ) - { - gain_controller->take_focus(); - } - else if ( ! strcmp( picked, "/Mute" ) ) - { - ((Fl_Button*)mute_controller->child(0))->value( ! - ((Fl_Button*)mute_controller->child(0))->value()); - - } - else if ( ! strcmp( picked, "Auto Output/On" ) ) - { - manual_connection( false ); - } - else if ( ! strcmp( picked, "Auto Output/Off" ) ) - { - manual_connection( true ); - } - else if ( ! strncmp( picked, "Auto Input/", strlen( "Auto Input/" ) )) - { - const char *s = index( picked, '/' ) + 1; - - if ( ! strcmp( s, "Off" ) ) - auto_input( NULL ); - else - auto_input( s ); - } -} - -void -Mixer_Strip::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Mixer_Strip*)v)->menu_cb( (Fl_Menu_*) w ); -} - -void -Mixer_Strip::auto_input ( const char *s ) -{ - if ( _auto_input ) - free( _auto_input ); - - _auto_input = NULL; - - if ( s ) - _auto_input = strdup( s ); - - mixer->auto_connect(); -} - -void -Mixer_Strip::manual_connection ( bool b ) -{ - _manual_connection = b; - output_connection_button->value(b); - - if ( chain() ) - { - if ( b ) - chain()->auto_disconnect_outputs(); - else - chain()->auto_connect_outputs(); - } -} - -static bool matches_pattern ( const char *pattern, Module::Port *p ) -{ - char group_name[256]; - char port_group[256]; - - if ( 2 == sscanf( pattern, "%[^/]/%[^\n]", group_name, port_group )) - { - if ( strcmp( group_name, "*" ) && - strcmp( group_name, p->module()->chain()->strip()->group()->name() )) - { - /* group mismatch */ - return false; - } - - /* group matches... try port group */ - if ( ! strcmp( port_group, "mains" ) ) - { - if ( index( p->jack_port()->name(), '/' ) ) - return false; - else - return true; - } - else - { - const char *pn = p->jack_port()->name(); - const char *n = rindex( pn, '/' ); - - if ( n ) - { -// *n = 0; - if ( ! strncmp( port_group, pn, ( n - 1 ) - pn ) ) - return true; - else - return false; - } - else - return false; - } - } - - return false; -} - - -#include "JACK_Module.H" - -void -Mixer_Strip::auto_connect_outputs ( void ) -{ - chain()->auto_connect_outputs(); -} - -bool -Mixer_Strip::has_group_affinity ( void ) const -{ - return _auto_input && strncmp( _auto_input, "*/", 2 ); -} - -bool -Mixer_Strip::maybe_auto_connect_output ( Module::Port *p ) -{ - if ( p->module()->chain()->strip()->_manual_connection ) - return true; - - if ( p->module()->chain()->strip() == this ) - /* don't auto connect to self! */ - return false; - - if ( ! _auto_input ) - { - /* break any previous connection between this port and this module */ - p->disconnect_from_strip(this); - } - - if ( _auto_input && matches_pattern( _auto_input, p ) ) - { - /* break any prior auto-connection */ - p->disconnect(); - - // FIXME: Find a better way to get the port index. - const char* jack_name = p->jack_port()->jack_name(); - - /* get port number */ - const char *s = rindex( jack_name, '-' ); - unsigned int n = atoi( s + 1 ) - 1; - - /* FIXME: safe assumption? */ - JACK_Module *m = (JACK_Module*)chain()->module(0); - - if ( !m ) - { - /* no jack module in the chian... may be in the process of adding the JACK module to the chain... i.e in log replay when loading a project. */ - return false; - } - - if ( n >= m->aux_audio_input.size() ) - { -// DMESSAGE( "No port to connect to at this index"); - return false; - } - - m->aux_audio_input[n].connect_to( p ); - - if ( p->module()->is_default() ) - { - /* only do this for mains */ - p->module()->chain()->strip()->output_connection_button->copy_label( name() ); - p->module()->chain()->strip()->output_connection_button->labelcolor( FL_FOREGROUND_COLOR ); - } - - return true; - } - - return false; -} - -/** build the context menu */ -Fl_Menu_Button & -Mixer_Strip::menu ( void ) const -{ - static Fl_Menu_Button m( 0, 0, 0, 0, "Strip" ); - static char label[256]; - - snprintf( label, sizeof(label), "Strip/%s", name() ); - m.label( label ); - -// int c = output.size(); - - m.clear(); - - std::list sl = mixer->get_auto_connect_targets(); - - - m.add( "Auto Output/On", 0, 0, 0, FL_MENU_RADIO | ( _manual_connection ? 0 : FL_MENU_VALUE ) ); - m.add( "Auto Output/Off", 0, 0, 0, FL_MENU_RADIO | ( ! _manual_connection ? 0 : FL_MENU_VALUE ) ); - m.add( "Auto Input/Off", 0, 0, 0, FL_MENU_DIVIDER | FL_MENU_RADIO | ( _auto_input ? 0 : FL_MENU_VALUE ) ); - - for ( std::list::iterator i = sl.begin(); i != sl.end(); i++ ) - { - char *s; - asprintf( &s, "Auto Input/%s", i->c_str() ); - - m.add( s, 0,0,0, FL_MENU_RADIO | ( _auto_input && !strcmp( _auto_input, i->c_str() ) ? FL_MENU_VALUE : 0 )); - free(s ); - } - - m.add( "Width/Narrow", 'n', 0, 0, FL_MENU_RADIO | ( ! width_button->value() ? FL_MENU_VALUE : 0 )); - m.add( "Width/Wide", 'w', 0, 0, FL_MENU_RADIO | ( width_button->value() ? FL_MENU_VALUE : 0 ) ); - m.add( "View/Fader", 'f', 0, 0, FL_MENU_RADIO | ( 0 == tab_button->value() ? FL_MENU_VALUE : 0 ) ); - m.add( "View/Signal", 's', 0, 0, FL_MENU_RADIO | ( 1 == tab_button->value() ? FL_MENU_VALUE : 0 ) ); - m.add( "Mute", 'm', 0, 0, 0 ); -// ( 1 == mute_controller->control_output[0].connected_port()->control_value() ? FL_MENU_VALUE : 0 ) ); - m.add( "Gain", 'g', 0, 0 ); - m.add( "Move Left", '[', 0, 0 ); - m.add( "Move Right", ']', 0, 0 ); - m.add( "Color", 0, 0, 0 ); - m.add( "Copy", FL_CTRL + 'c', 0, 0 ); - m.add( "Export Strip", 0, 0, 0 ); - m.add( "Rename", FL_CTRL + 'n', 0, 0 ); - m.add( "Remove", FL_Delete, 0, 0 ); - - menu_set_callback( const_cast(m.menu()), &Mixer_Strip::menu_cb, (void*)this ); - - return m; -} - -Controller_Module * -Mixer_Strip::spatializer ( void ) -{ - return spatialization_controller; -} - -void -Mixer_Strip::get_output_ports ( std::list &ports ) -{ - _chain->get_output_ports(ports); -} - -int -Mixer_Strip::handle ( int m ) -{ - static int _button = 0; - - Logger log( this ); - - static Fl_Widget *dragging = NULL; - - if ( Fl_Group::handle( m ) ) - return 1; - - switch ( m ) - { - case FL_FOCUS: - damage( FL_DAMAGE_USER1 ); - return 1; - case FL_UNFOCUS: - damage( FL_DAMAGE_USER1 ); - return 1; - } - - /* if ( m == FL_PUSH ) */ - /* take_focus(); */ - - switch ( m ) - { - case FL_KEYBOARD: - { - if ( Fl::event_key() == FL_Menu ) - { - menu_popup( &menu(), x(), y() ); - return 1; - } - else - return menu().test_shortcut() != 0; - break; - } - case FL_PUSH: - if ( Fl::event_button1() && Fl::event_inside( color_box ) ) - dragging = this; - else - dragging = NULL; - - _button = Fl::event_button(); - - return 1; - - break; - - case FL_DRAG: - return 1; - break; - case FL_RELEASE: - if ( dragging == this && ! Fl::event_is_click() ) - { - mixer->insert( this, mixer->event_inside() ); - /* FIXME: do better! */ - mixer->redraw(); - dragging = NULL; - return 1; - } - - dragging = NULL; - - int b = _button; - _button = 0; - - /* if ( 1 == b ) */ - /* { */ - /* take_focus(); */ - /* } */ - /* else */ - if ( 3 == b ) - { - menu_popup( &menu() ); - return 1; - } - break; - } - - return 0; -} - -void -Mixer_Strip::send_feedback ( void ) -{ - if ( _chain ) - _chain->send_feedback(); -} - -int -Mixer_Strip::number ( void ) const -{ - return mixer->find_strip( this ); -} - -/************/ -/* Commands */ -/************/ - -void -Mixer_Strip::command_toggle_fader_view ( void ) -{ - tab_button->value( ! tab_button->value() ); - tab_button->do_callback(); -} - -void -Mixer_Strip::command_move_left ( void ) -{ - mixer->move_left( this ); -} - -void -Mixer_Strip::command_move_right ( void ) -{ - mixer->move_right( this ); -} - -void -Mixer_Strip::command_close ( void ) -{ - Fl::delete_widget( this ); -} - -void -Mixer_Strip::command_rename ( const char * s ) -{ - name( s ); -} - -void -Mixer_Strip::command_width ( bool b ) -{ - width_button->value( b ); - width_button->do_callback(); -} - -void -Mixer_Strip::command_view ( bool b ) -{ - tab_button->value( b ); - tab_button->do_callback(); -} diff --git a/mixer/src/Mixer_Strip.H b/mixer/src/Mixer_Strip.H deleted file mode 100644 index ce7967a..0000000 --- a/mixer/src/Mixer_Strip.H +++ /dev/null @@ -1,188 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2010 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include "DPM.H" -#include "Panner.H" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "../FL/Fl_Sometimes_Input.H" - -#include "Loggable.H" -class Chain; -class Fl_Flowpack; -class Controller_Module; -class Meter_Indicator_Module; -class Module; -class Fl_Flip_Button; -class Fl_Input; -class Fl_Menu_; -class Fl_Menu_Button; -class Fl_Choice; -class Group; - -#include "Module.H" - -class Mixer_Strip : public Fl_Group, public Loggable { - -public: - - static int min_h ( void ) { return 333; } - - Mixer_Strip( const char *strip_name ); - Mixer_Strip(); /* for log create */ - virtual ~Mixer_Strip(); - - void chain ( Chain *c ); - Chain *chain ( void ) { return _chain; } - - virtual void log_children ( void ) const; - - virtual void color ( Fl_Color c ); - virtual Fl_Color color ( void ) const; - - LOG_CREATE_FUNC( Mixer_Strip ); - - static void configure_outputs ( Fl_Widget *o, void *v ); - void configure_outputs ( void ); - - bool configure_ports ( int n ); - - void handle_module_added ( Module *m ); - void handle_module_removed ( Module *m ); - - void update ( void ); - - void name ( const char *name ); - const char *name ( void ) const { return label(); } - -private: - - char *_auto_input; - void auto_input ( const char *s ); - - unsigned int _dsp_load_index; - - /* used to defer setting the mode of the gain controller until the - chain has been added and the controller connected to a default - module */ - int _gain_controller_mode; - int _mute_controller_mode; - bool _manual_connection; - - Fl_Menu_Button *output_connection_button; - Fl_Flip_Button *width_button; - Fl_Flip_Button *tab_button; - Fl_Button *close_button; - Fl_Input *name_field; - Fl_Choice *group_choice; - - Fl_Flowpack *controls_pack; - Fl_Group *tab_group; - Fl_Group *signal_tab; - Fl_Group *fader_tab; - Fl_Pack *panner_pack; - - Chain *_chain; - Group *_group; - - Fl_Box *spatialization_label; - Controller_Module *gain_controller; - Controller_Module *mute_controller; - Controller_Module *jack_input_controller; - Controller_Module *spatialization_controller; - Meter_Indicator_Module *meter_indicator; - - Fl_Progress *dsp_load_progress; - - Fl_Box *color_box; - - nframes_t nframes; - - Fl_Color _color; - - void init ( ); - void cb_handle(Fl_Widget*); - static void cb_handle(Fl_Widget*, void*); - - void set_tab ( void ); - - void update_port_names ( void ); - - void menu_cb ( const Fl_Menu_ *m ); - static void menu_cb ( Fl_Widget *w, void *v ); - Fl_Menu_Button & menu ( void ) const; - - static void snapshot ( void *v ); - void snapshot ( void ); - bool export_strip ( const char *filename ); - - void set_spatializer_visibility ( void ); - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - virtual int handle ( int m ); - virtual void draw ( void ); - -public: - - void manual_connection ( bool b ); - bool has_group_affinity ( void ) const; - void auto_connect_outputs ( void ); - bool maybe_auto_connect_output ( Module::Port *p ); - - void get_output_ports ( std::list &ports ); - - void update_group_choice ( void ); - - Controller_Module *spatializer ( void ); - - Group *group ( void ) { return _group;} - - // int group ( void ) const; - void group ( Group * ); - void send_feedback ( void ); - int number ( void ) const; - static bool import_strip ( const char *filename ); - - void command_toggle_fader_view ( void ); - void command_move_left ( void ); - void command_move_right ( void ); - void command_close ( void ); - void command_rename ( const char * s ); - void command_width ( bool b ); - void command_view ( bool b ); - -}; diff --git a/mixer/src/Module.C b/mixer/src/Module.C deleted file mode 100644 index ea712d3..0000000 --- a/mixer/src/Module.C +++ /dev/null @@ -1,1426 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Module.H" -#include -#include - -#include -#include -#include - -#include "Module_Parameter_Editor.H" -#include "Chain.H" - -#include "JACK_Module.H" -#include "Gain_Module.H" -#include "Mono_Pan_Module.H" -#include "Meter_Module.H" -#include "Plugin_Module.H" -#include "AUX_Module.H" -#include "Spatializer_Module.H" - -#include "FL/focus_frame.H" -#include -#include "FL/test_press.H" -#include "FL/menu_popup.H" -#include "Mixer.H" - -#include "Plugin_Chooser.H" -#include "OSC/Endpoint.H" - -#include "string_util.h" - - - -nframes_t Module::_sample_rate = 0; -Module *Module::_copied_module_empty = 0; -char *Module::_copied_module_settings = 0; - - - -Module::Module ( int W, int H, const char *L ) : Fl_Group( 0, 0, W, H, L ) -{ - init(); -} - -Module::Module ( bool is_default, int W, int H, const char *L ) : Fl_Group( 0, 0, W, H, L ), Loggable( !is_default ) -{ - init(); - - this->is_default( is_default ); -} - -Module::Module ( ) : Fl_Group( 0, 0, 50, 50, "Unnamed" ) -{ - init(); -} - -Module::~Module ( ) -{ - /* we assume that the client for this chain is already locked */ - - if ( _editor ) - { - delete _editor; - _editor = NULL; - } - - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - audio_input[i].disconnect(); - for ( unsigned int i = 0; i < audio_output.size(); ++i ) - audio_output[i].disconnect(); - for ( unsigned int i = 0; i < aux_audio_input.size(); ++i ) - { - aux_audio_input[i].disconnect(); - aux_audio_input[i].jack_port()->shutdown(); - delete aux_audio_input[i].jack_port(); - } - for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) - { - aux_audio_output[i].disconnect(); - aux_audio_output[i].jack_port()->shutdown(); - delete aux_audio_output[i].jack_port(); - } - for ( unsigned int i = 0; i < control_input.size(); ++i ) - { - /* destroy connected Controller_Module */ - if ( control_input[i].connected() ) - { - Module *o = (Module*)control_input[i].connected_port()->module(); - - if ( ! o->is_default() ) - { - control_input[i].disconnect(); - - DMESSAGE( "Deleting connected module %s", o->label() ); - - delete o; - } - else - { - control_input[i].disconnect(); - } - - } - - control_input[i].destroy_osc_port(); - } - for ( unsigned int i = 0; i < control_output.size(); ++i ) - control_output[i].disconnect(); - - audio_input.clear(); - audio_output.clear(); - - control_input.clear(); - control_output.clear(); - - if ( parent() ) - parent()->remove( this ); -} - - - - -void -Module::init ( void ) -{ - - /* we use pointers to these vector elements for port auto connection stuff and need to prevent reallocation from invalidating them. */ - audio_input.reserve(16); - audio_output.reserve(16); - control_input.reserve(16); - control_output.reserve(16); - aux_audio_input.reserve(16); - aux_audio_output.reserve(16); - -// _latency = 0; - _is_default = false; - _editor = 0; - _chain = 0; - _instances = 1; - _bypass = 0; - - box( FL_UP_BOX ); - labeltype( FL_NO_LABEL ); - align( FL_ALIGN_CENTER | FL_ALIGN_INSIDE ); - set_visible_focus(); - selection_color( FL_YELLOW ); - - labelsize(12); - color( fl_rgb_color( 122,190,200 ) ); - tooltip(); -} - -void -Module::update_tooltip ( void ) -{ - char *s; - asprintf( &s, "Left click to edit parameters; Ctrl + left click to select; right click or MENU key for menu. (info: latency: %lu)", (unsigned long) get_module_latency() ); - - copy_tooltip(s); - free(s); -} - -void -Module::get ( Log_Entry &e ) const -{ -// e.add( ":name", label() ); -// e.add( ":color", (unsigned long)color()); - { - char *s = get_parameters(); - if ( strlen( s ) ) - e.add( ":parameter_values", s ); - delete[] s; - } - e.add( ":is_default", is_default() ); - e.add( ":chain", chain() ); - e.add( ":active", ! bypass() ); -} - -bool -Module::copy ( void ) const -{ - Module *m = clone_empty(); - - if ( ! m ) - { - DMESSAGE( "Module \"%s\" doesn't support cloning", name() ); - return false; - } - - Log_Entry *ne = new Log_Entry(); - - _copied_module_empty = m; - - { - Log_Entry e; - get( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - /* we don't want this module to get added to the current - chain... */ - if ( !( !strcmp( s, ":chain" ) || - !strcmp( s, ":is_default" ) ) ) - { - DMESSAGE( "%s = %s", s, v ); - ne->add_raw( s, v ); - } - } - } - - _copied_module_settings = ne->print(); - - return true; -} - -void -Module::paste_before ( void ) -{ - Module *m = _copied_module_empty; - - Log_Entry le( _copied_module_settings ); - le.remove( ":chain" ); - - char *print = le.print(); - - DMESSAGE( "Pasting settings: %s", print ); - - free( print ); - - m->set( le ); - - if ( ! chain()->insert( this, m ) ) - { - fl_alert( "Copied module cannot be inserted at this point in the chain" ); - } - - free( _copied_module_settings ); - _copied_module_settings = NULL; - _copied_module_empty = NULL; - - /* set up for another paste */ - m->copy(); -} - - - -void -Module::Port::disconnect_from_strip ( Mixer_Strip *o ) -{ - for ( std::list::iterator i = _connected.begin(); i != _connected.end(); i++ ) - { - Port *p = *i; - - if ( p->module()->chain()->strip() == o ) - { - /* iterator about to be invalidated... */ - i = _connected.erase(i); - - disconnect(p); - } - } -} - -const char * -Module::Port::osc_number_path ( void ) -{ - if ( ! _scaled_signal ) - return NULL; - - int n = _module->chain()->strip()->number(); - - if ( _by_number_path && n == _by_number_number ) - return _by_number_path; - - if ( _by_number_path ) - free( _by_number_path ); - - char *rem; - char *client_name; - char *strip_name; - - if ( 3 != sscanf( _scaled_signal->path(), "%m[^/]/strip/%m[^/]/%m[^\n]", &client_name, &strip_name, &rem ) ) - return NULL; - - free( strip_name ); - - char *path; - asprintf( &path, "%s/strip#/%i/%s", client_name, n, rem ); - - free( client_name ); - free( rem ); - - _by_number_path = path; - _by_number_number = n; - - return path; -} - -void -Module::Port::send_feedback ( void ) -{ - float f = control_value(); - - if ( hints.ranged ) - { - // scale value to range. - - float scale = hints.maximum - hints.minimum; - float offset = hints.minimum; - - f = ( f - offset ) / scale; - } - - if ( f > 1.0 ) - f = 1.0; - else if ( f < 0.0 ) - f = 0.0; - - if ( _scaled_signal ) - { - /* send feedback for by_name signal */ - mixer->osc_endpoint->send_feedback( _scaled_signal->path(), f ); - - /* send feedback for by number signal */ - mixer->osc_endpoint->send_feedback( osc_number_path(), f ); - } -} - -void -Module::send_feedback ( void ) -{ - for ( int i = 0; i < ncontrol_inputs(); i++ ) - control_input[i].send_feedback(); -} - -void -Module::handle_control_changed ( Port *p ) -{ - if ( _editor ) - _editor->handle_control_changed ( p ); - - p->send_feedback(); -} - -/* bool */ -/* Module::Port::connected_osc ( void ) const */ -/* { */ -/* if ( _scaled_signal ) */ -/* return _scaled_signal->connected(); */ -/* else */ -/* return false; */ -/* } */ - -char * -Module::Port::generate_osc_path () -{ - const Port *p = this; - - char *path = NULL; - - // /strip/STRIPNAME/MODULENAME/CONTROLNAME - - if ( ! p->hints.visible ) - { - return NULL; - } - - int n = module()->chain()->get_module_instance_number( module() ); - - if ( n > 0 ) - asprintf( &path, "/strip/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() ); - else - asprintf( &path, "/strip/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() ); - - char *s = escape_url( path ); - - free( path ); - - path = s; - - return path; -} - -void -Module::Port::handle_signal_connection_state_changed ( OSC::Signal *, void *o ) -{ - ((Module::Port*)o)->module()->redraw(); -} - -void -Module::Port::change_osc_path ( char *path ) -{ - if ( path ) - { - char *scaled_path = path; - char *unscaled_path = NULL; - - asprintf( &unscaled_path, "%s/unscaled", path ); - - if ( NULL == _scaled_signal ) - { - float scaled_default = 0.5f; - - if ( hints.ranged ) - { - float scale = hints.maximum - hints.minimum; - float offset = hints.minimum; - - scaled_default = ( hints.default_value - offset ) / scale; - } - - _scaled_signal = mixer->osc_endpoint->add_signal( scaled_path, - OSC::Signal::Input, - 0.0, 1.0, scaled_default, - &Module::Port::osc_control_change_cv, this ); - - - _scaled_signal->connection_state_callback( handle_signal_connection_state_changed, this ); - - _unscaled_signal = mixer->osc_endpoint->add_signal( unscaled_path, - OSC::Signal::Input, - hints.minimum, hints.maximum, hints.default_value, - &Module::Port::osc_control_change_exact, this ); - } - else - { - DMESSAGE( "Renaming OSC signals" ); - - _scaled_signal->rename( scaled_path ); - _unscaled_signal->rename( unscaled_path ); - } - - free( unscaled_path ); - /* this was path, it's ok to free because it was malloc()'d in generate_osc_path */ - free( scaled_path ); - } -} - - -int -Module::Port::osc_control_change_exact ( float v, void *user_data ) -{ - Module::Port *p = (Module::Port*)user_data; - - Fl::lock(); - - float f = v; - - if ( p->hints.ranged ) - { - if ( f > p->hints.maximum ) - f = p->hints.maximum; - else if ( f < p->hints.minimum ) - f = p->hints.minimum; - - if ( Hints::BOOLEAN == p->hints.type ) - f = f > (p->hints.maximum - (p->hints.maximum - p->hints.minimum)) * 0.5f ? - p->hints.maximum : - p->hints.minimum; - } - - - p->control_value( f ); - - Fl::unlock(); - -// mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, f ); - - return 0; -} - -int -Module::Port::osc_control_change_cv ( float v, void *user_data ) -{ - Module::Port *p = (Module::Port*)user_data; - - float f = v; - - Fl::lock(); - - // clamp value to control voltage range. - if ( f > 1.0 ) - f = 1.0; - else if ( f < 0.0 ) - f = 0.0; - - if ( p->hints.ranged ) - { - if ( Hints::BOOLEAN == p->hints.type ) - f = f > 0.5f ? p->hints.maximum : p->hints.minimum; - - // scale value to range. - - float scale = p->hints.maximum - p->hints.minimum; - float offset = p->hints.minimum; - - f = ( f * scale ) + offset; - } - - p->control_value( f ); - - Fl::unlock(); -// mixer->osc_endpoint->send( lo_message_get_source( msg ), "/reply", path, f ); - - return 0; -} - - -void -Module::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! ( strcmp( s, ":is_default" ) ) ) - { - is_default( atoi( v ) ); - } - else if ( ! strcmp( s, ":chain" ) ) - { - /* This trickiness is because we may need to know the name of - our chain before we actually get added to it. */ - int i; - sscanf( v, "%X", &i ); - Chain *t = (Chain*)Loggable::find( i ); - - assert( t ); - - chain( t ); - } - } - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - -/* if ( ! strcmp( s, ":name" ) ) */ -/* label( v ); */ - if ( ! strcmp( s, ":parameter_values" ) ) - { - set_parameters( v ); - } - else if ( ! ( strcmp( s, ":active" ) ) ) - { - bypass( ! atoi( v ) ); - } - else if ( ! strcmp( s, ":chain" ) ) - { - int i; - sscanf( v, "%X", &i ); - Chain *t = (Chain*)Loggable::find( i ); - - assert( t ); - - t->add( this ); - } - } -} - - - - -void -Module::chain ( Chain *v ) -{ - if ( _chain != v ) - { - DMESSAGE( "Adding module %s in to chain %s", label(), v ? v->name() : "NULL" ); - - _chain = v; - - for ( int i = 0; i < ncontrol_inputs(); ++i ) - { - control_input[i].update_osc_port(); - } - } - else - { - DMESSAGE( "Module %s already belongs to chain %s", label(), v ? v->name() : "NULL" ); - } -} - -/* return a string serializing this module's parameter settings. The - format is 1.0:2.0:... Where 1.0 is the value of the first control - input, 2.0 is the value of the second control input etc. -*/ -char * -Module::get_parameters ( void ) const -{ - char *s = new char[1024]; - s[0] = 0; - char *sp = s; - - if ( control_input.size() ) - { - for ( unsigned int i = 0; i < control_input.size(); ++i ) - sp += snprintf( sp, 1024 - (sp - s),"%f:", control_input[i].control_value() ); - - *(sp - 1) = '\0'; - } - - return s; -} - -void -Module::set_parameters ( const char *parameters ) -{ - char *s = strdup( parameters ); - - char *start = s; - unsigned int i = 0; - for ( char *sp = s; ; ++sp ) - { - if ( ':' == *sp || '\0' == *sp ) - { - char was = *sp; - - *sp = '\0'; - - DMESSAGE( start ); - - if ( i < control_input.size() ) - control_input[i].control_value( atof( start ) ); - else - { - WARNING( "Module has no parameter at index %i", i ); - break; - } - - i++; - - if ( '\0' == was ) - break; - - start = sp + 1; - } - } - - free( s ); -} - - - -void -Module::draw_box ( int tx, int ty, int tw, int th ) -{ - fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); - - fl_push_clip( tx, ty, tw, th ); - - Fl_Color c = color(); - - if ( ! active_r() ) - c = fl_inactive( c ); - - int spacing = w() / instances(); - for ( int i = instances(); i--; ) - { - fl_draw_box( box(), tx + (spacing * i), ty, tw / instances(), th, c ); - } - - - if ( audio_input.size() && audio_output.size() ) - { - /* maybe draw control indicators */ - if ( control_input.size() ) - { - fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 4, 5, 5, is_being_controlled() ? FL_YELLOW : fl_inactive( FL_YELLOW ) ); - - /* fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + th - 8, 5, 5, is_being_controlled_osc() ? FL_YELLOW : fl_inactive( FL_YELLOW ) ); */ - } - - if ( control_output.size() ) - fl_draw_box( FL_ROUNDED_BOX, tx + tw - 8, ty + 4, 5, 5, is_controlling() ? FL_YELLOW : fl_inactive( FL_YELLOW ) ); - } - - fl_push_clip( tx + Fl::box_dx(box()), ty + Fl::box_dy(box()), tw - Fl::box_dw(box()), th - Fl::box_dh(box()) ); - - Fl_Group::draw_children(); - - fl_pop_clip(); - - if ( focused_r( this ) ) - draw_focus_frame( tx,ty,tw,th, selection_color() ); - - fl_pop_clip(); -} - -#include "SpectrumView.H" -#include - - -bool -Module::show_analysis_window ( void ) -{ - /* use a large window for more accuracy at low frequencies */ - nframes_t nframes = sample_rate() / 2; - float *buf = new float[nframes]; - - memset( buf, 0, sizeof(float) * nframes ); - - buf[0] = 1; - - if ( ! get_impulse_response( buf, nframes ) ) - { - // return false; - } - - Fl_Double_Window *w = new Fl_Double_Window( 1000, 500 ); - - { - SpectrumView * o = new SpectrumView( 25,25, 1000 - 50, 500 - 50, label() ); - o->labelsize(10); - o->align(FL_ALIGN_RIGHT|FL_ALIGN_TOP); - o->sample_rate( sample_rate() ); - o->data( buf, nframes ); - } - - w->end(); - - w->show(); - - while ( w->shown() ) - Fl::wait(); - - delete w; - - return true; -} - -void -Module::draw_label ( int tx, int ty, int tw, int th ) -{ - bbox( tx, ty, tw, th ); - - if ( ! label() ) - return; - - char *lab = strdup( label() ); - - Fl_Color c = fl_contrast( FL_FOREGROUND_COLOR, color() ); - - fl_color( active_r() && ! bypass() ? c : fl_inactive(c) ); - - fl_font( FL_HELVETICA, labelsize() ); - - char *di = strstr( lab, " -" ); - - if ( ! di ) - di = strstr( lab, " " ); - - if ( di ) - *di = '\0'; - - int LW = fl_width( lab ); - char *s = NULL; - - bool initial = true; - if ( LW > tw ) - { - s = new char[strlen(lab) + 1]; - char *sp = s; - const char *lp = lab; - - for ( ; *lp; ++lp ) - { - bool skip = false; - - switch ( *lp ) - { - case ' ': - initial = true; - skip = false; - break; - case 'i': case 'e': case 'o': case 'u': case 'a': - skip = ! initial; - initial = false; - break; - default: - skip = false; - initial = false; - break; - } - - if ( ! skip ) - *(sp++) = *lp; - } - - *sp = '\0'; - - } - - fl_draw( s ? s : lab, tx, ty, tw, th, align() | FL_ALIGN_CLIP ); - - if ( bypass() ) - { - fl_color( fl_color_add_alpha( fl_color(), 127 ) ); - fl_line_style( FL_SOLID, 2 ); - fl_line( tx, ty + th * 0.5, tx + tw, ty + th * 0.5 ); - fl_line_style( FL_SOLID, 0 ); - } - - - free(lab); - - if ( s ) - delete[] s; -} - -void -Module::insert_menu_cb ( const Fl_Menu_ *m ) -{ - - const char * picked = m->mvalue()->label(); - - DMESSAGE("picked = %s", picked ); - - Module *mod = NULL; - - if ( !strcmp( picked, "Aux" ) ) - { - int n = 0; - for ( int i = 0; i < chain()->modules(); i++ ) - { - if ( !strcmp( chain()->module(i)->name(), "AUX" ) ) - n++; - } - - AUX_Module *jm = new AUX_Module(); - jm->chain( chain() ); - jm->number( n ); - jm->configure_inputs( ninputs() ); - jm->configure_outputs( ninputs() ); - jm->initialize(); - - mod = jm; - } - if ( !strcmp( picked, "Spatializer" ) ) - { - int n = 0; - for ( int i = 0; i < chain()->modules(); i++ ) - { - if ( !strcmp( chain()->module(i)->name(), "Spatializer" ) ) - n++; - } - - if ( n == 0 ) - { - Spatializer_Module *jm = new Spatializer_Module(); - - jm->chain( chain() ); -// jm->number( n ); -// jm->configure_inputs( ninputs() ); -// jm->configure_outputs( ninputs() ); - jm->initialize(); - - mod = jm; - } - } - else if ( !strcmp( picked, "Gain" ) ) - mod = new Gain_Module(); - /* else if ( !strcmp( picked, "Spatializer" ) ) */ - /* mod = new Spatializer_Module(); */ - else if ( !strcmp( picked, "Meter" ) ) - mod = new Meter_Module(); - else if ( !strcmp( picked, "Mono Pan" )) - mod = new Mono_Pan_Module(); - else if ( !strcmp(picked, "Plugin" )) - { - unsigned long id = Plugin_Chooser::plugin_chooser( this->ninputs() ); - - if ( id == 0 ) - return; - - Plugin_Module *m = new Plugin_Module(); - - m->load( id ); - - mod = m; - } - - if ( mod ) - { - if ( ! chain()->insert( this, mod ) ) - { - fl_alert( "Cannot insert this module at this point in the chain" ); - delete mod; - return; - } - - redraw(); - } -} - -void -Module::insert_menu_cb ( Fl_Widget *w, void *v ) -{ - ((Module*)v)->insert_menu_cb( (Fl_Menu_*) w ); -} - -void -Module::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[256]; - - if ( ! m->mvalue() || m->mvalue()->flags & FL_SUBMENU_POINTER || m->mvalue()->flags & FL_SUBMENU ) - return; - - strncpy( picked, m->mvalue()->label(), sizeof( picked ) ); - -// m->item_pathname( picked, sizeof( picked ) ); - - DMESSAGE( "%s", picked ); - - Logger log( this ); - - if ( ! strcmp( picked, "Edit Parameters" ) ) - command_open_parameter_editor(); - else if ( ! strcmp( picked, "Bypass" ) ) - { - if ( ! bypassable() ) - { - fl_alert( "Due to its channel configuration, this module cannot be bypassed." ); - } - else - { - bypass( !bypass() ); - redraw(); - } - } - else if ( ! strcmp( picked, "Cut" ) ) - { - if ( copy() ) - { - chain()->remove( this ); - Fl::delete_widget( this ); - } - } - else if ( ! strcmp( picked, "Copy" ) ) - { - copy(); - } - else if ( ! strcmp( picked, "Paste" ) ) - { - paste_before(); - } - else if ( ! strcmp( picked, "Show Analysis" ) ) - { - show_analysis_window(); - } - else if ( ! strcmp( picked, "Remove" ) ) - command_remove(); -} - -void -Module::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Module*)v)->menu_cb( (Fl_Menu_*) w ); -} - -/** build the context menu */ -Fl_Menu_Button & -Module::menu ( void ) const -{ - static Fl_Menu_Button m( 0, 0, 0, 0, "Module" ); - static Fl_Menu_Button *insert_menu = NULL; - - if ( ! insert_menu ) - { - insert_menu = new Fl_Menu_Button( 0, 0, 0, 0 ); - - insert_menu->add( "Gain", 0, 0 ); - insert_menu->add( "Meter", 0, 0 ); - insert_menu->add( "Mono Pan", 0, 0 ); - insert_menu->add( "Aux", 0, 0 ); - insert_menu->add( "Spatializer", 0, 0 ); - insert_menu->add( "Plugin", 0, 0 ); - - insert_menu->callback( &Module::insert_menu_cb, (void*)this ); - } - - m.clear(); - - m.add( "Insert", 0, &Module::menu_cb, (void*)this, 0); - m.add( "Insert", 0, &Module::menu_cb, const_cast< Fl_Menu_Item *>( insert_menu->menu() ), FL_SUBMENU_POINTER ); - m.add( "Edit Parameters", ' ', &Module::menu_cb, (void*)this, 0 ); - m.add( "Show Analysis", 's', &Module::menu_cb, (void*)this, 0); - m.add( "Bypass", 'b', &Module::menu_cb, (void*)this, FL_MENU_TOGGLE | ( bypass() ? FL_MENU_VALUE : 0 ) ); - m.add( "Cut", FL_CTRL + 'x', &Module::menu_cb, (void*)this, is_default() ? FL_MENU_INACTIVE : 0 ); - m.add( "Copy", FL_CTRL + 'c', &Module::menu_cb, (void*)this, is_default() ? FL_MENU_INACTIVE : 0 ); - m.add( "Paste", FL_CTRL + 'v', &Module::menu_cb, (void*)this, _copied_module_empty ? 0 : FL_MENU_INACTIVE ); - - m.add( "Remove", FL_Delete, &Module::menu_cb, (void*)this ); - -// menu_set_callback( menu, &Module::menu_cb, (void*)this ); - m.callback( &Module::insert_menu_cb, (void*)this ); - - return m; -} - -void -Module::handle_chain_name_changed ( ) -{ - // pass it along to our connected Controller_Modules, if any. - for ( int i = 0; i < ncontrol_inputs(); ++i ) - { - if ( control_input[i].connected() ) - control_input[i].connected_port()->module()->handle_chain_name_changed(); - - control_input[i].update_osc_port(); - } - - if ( ! chain()->strip()->group()->single() ) - { - /* we have to rename our JACK ports... */ - for ( unsigned int i = 0; i < aux_audio_input.size(); i++ ) - { - aux_audio_input[i].jack_port()->trackname( chain()->name() ); - aux_audio_input[i].jack_port()->rename(); - } - for ( unsigned int i = 0; i < aux_audio_output.size(); i++ ) - { - aux_audio_output[i].jack_port()->trackname( chain()->name() ); - aux_audio_output[i].jack_port()->rename(); - } - } -} - -int -Module::handle ( int m ) -{ - static unsigned long _event_state = 0; - - unsigned long evstate = Fl::event_state(); - - switch ( m ) - { - case FL_ENTER: -// Fl::focus(this); - case FL_LEAVE: - return 1; - } - - if ( Fl_Group::handle( m ) ) - return 1; - - switch ( m ) - { - case FL_KEYBOARD: - { - if ( Fl::event_key() == FL_Menu ) - { - menu_popup( &menu(), x(), y() ); - return 1; - } - else - return menu().test_shortcut() != 0; - } - case FL_PUSH: - take_focus(); - _event_state = evstate; - return 1; - // if ( Fl::visible_focus() && handle( FL_FOCUS )) Fl::focus(this); - case FL_DRAG: - _event_state = evstate; - return 1; - case FL_RELEASE: - { - unsigned long e = _event_state; - _event_state = 0; - - if ( ! Fl::event_inside( this ) ) - return 1; - - if ( ( e & FL_BUTTON1 ) && ( e & FL_CTRL ) ) - { - Fl::focus(this); - return 1; - } - else if ( e & FL_BUTTON1 ) - { - command_open_parameter_editor(); - return 1; - } - else if ( e & FL_BUTTON3 && e & FL_CTRL ) - { - command_remove(); - return 1; - } - else if ( e & FL_BUTTON3 ) - { - menu_popup( &menu() ); - return 1; - } - else if ( e & FL_BUTTON2 ) - { - if ( !bypassable() ) - { - fl_alert( "Due to its channel configuration, this module cannot be bypassed." ); - } - else - { - bypass( !bypass() ); - redraw(); - } - return 1; - } - /* else */ - /* { */ - /* take_focus(); */ - /* } */ - - return 0; - } - case FL_FOCUS: - case FL_UNFOCUS: - redraw(); - return 1; - } - - return 0; -} - -/*************/ -/* AUX Ports */ -/*************/ - - -static char * -generate_port_name ( const char *aux, int direction, int n ) -{ - char *s; - asprintf( &s, "%s%s%s-%i", - aux ? aux : "", - aux ? "/" : "", - direction == JACK::Port::Input ? "in" : "out", - n + 1 ); - - return s; -} - -static void -jack_port_activation_error ( JACK::Port *p ) -{ - fl_alert( "Could not activate JACK port \"%s\"", p->name() ); -} - -/* freeze/disconnect all jack ports--used when changing groups */ -void -Module::freeze_ports ( void ) -{ - // pass it along to our connected Controller_Modules, if any. - for ( int i = 0; i < ncontrol_inputs(); ++i ) - { - if ( control_input[i].connected() ) - control_input[i].connected_port()->module()->freeze_ports(); - } - - for ( unsigned int i = 0; i < aux_audio_input.size(); ++i ) - { - aux_audio_input[i].jack_port()->freeze(); - aux_audio_input[i].jack_port()->shutdown(); - } - - for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) - { - aux_audio_output[i].jack_port()->freeze(); - aux_audio_output[i].jack_port()->shutdown(); - } -} - -/* rename and thaw all jack ports--used when changing groups */ -void -Module::thaw_ports ( void ) -{ - // pass it along to our connected Controller_Modules, if any. - for ( int i = 0; i < ncontrol_inputs(); ++i ) - { - if ( control_input[i].connected() ) - control_input[i].connected_port()->module()->thaw_ports(); - } - - const char *trackname = chain()->strip()->group()->single() ? NULL : chain()->name(); - - for ( unsigned int i = 0; i < aux_audio_input.size(); ++i ) - { - /* if we're entering a group we need to add the chain name - * prefix and if we're leaving one, we need to remove it */ - - aux_audio_input[i].jack_port()->client( chain()->client() ); - aux_audio_input[i].jack_port()->trackname( trackname ); - aux_audio_input[i].jack_port()->thaw(); - } - - for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) - { - /* if we're entering a group we won't actually be using our - * JACK output ports anymore, just mixing into the group outputs */ - aux_audio_output[i].jack_port()->client( chain()->client() ); - aux_audio_output[i].jack_port()->trackname( trackname ); - aux_audio_output[i].jack_port()->thaw(); - - mixer->maybe_auto_connect_output( &aux_audio_output[i] ); - } -} - -void -Module::auto_connect_outputs ( void ) -{ - for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) - { - mixer->maybe_auto_connect_output( &aux_audio_output[i] ); - } -} - -void -Module::auto_disconnect_outputs ( void ) -{ - for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) - { - Module::Port *p = &aux_audio_output[i]; - - if ( p->connected_port() ) - { - p->connected_port()->jack_port()->disconnect( p->jack_port()->jack_name() ); - p->disconnect(); - } - } -} - -void -Module::get_latency ( JACK::Port::direction_e dir, nframes_t *min, nframes_t *max ) const -{ - nframes_t tmin = JACK_MAX_FRAMES >> 1; - nframes_t tmax = 0; - - const std::vector *ports; - - if ( dir == JACK::Port::Input ) - ports = &aux_audio_input; - else - ports = &aux_audio_output; - - if ( ports->size() ) - { - for ( unsigned int i = 0; i < ports->size(); i++ ) - { - /* if ( ! ports->[i].jack_port()->connected() ) */ - /* continue; */ - - nframes_t min,max; - - (*ports)[i].jack_port()->get_latency( dir, &min, &max ); - - if ( min < tmin ) - tmin = min; - if ( max > tmax ) - tmax = max; - } - } - else - { - tmin = 0; - } - - *min = tmin; - *max = tmax; -} - -void -Module::set_latency ( JACK::Port::direction_e dir, nframes_t min, nframes_t max ) -{ - if ( dir == JACK::Port::Output ) - { - for ( unsigned int i = 0; i < aux_audio_input.size(); i++ ) - aux_audio_input[i].jack_port()->set_latency( dir, min, max ); - } - else - { - for ( unsigned int i = 0; i < aux_audio_output.size(); i++ ) - aux_audio_output[i].jack_port()->set_latency( dir, min, max ); - } -} - - -bool -Module::add_aux_port ( bool input, const char *prefix, int i, JACK::Port::type_e type ) -{ - const char *trackname = chain()->strip()->group()->single() ? NULL : chain()->name(); - - JACK::Port::direction_e direction = input ? JACK::Port::Input : JACK::Port::Output; - - char *portname = generate_port_name( prefix, direction, i ); - - JACK::Port *po = new JACK::Port( chain()->client(), trackname, portname, direction, type ); - - free(portname); - - if ( ! po->activate() ) - { - jack_port_activation_error( po ); - return false; - } - - if ( po->valid() ) - { - if ( input ) - { - Module::Port mp( (Module*)this, Module::Port::INPUT, Module::Port::AUX_AUDIO ); - - mp.jack_port( po ); - - aux_audio_input.push_back( mp ); - } - else - { - Module::Port mp( (Module*)this, Module::Port::OUTPUT, Module::Port::AUX_AUDIO ); - - mp.jack_port( po ); - - aux_audio_output.push_back( mp ); - } - } - else - { - delete po; - return false; - } - - return true; -} - -bool -Module::add_aux_audio_output( const char *prefix, int i ) -{ - bool r = add_aux_port ( false, prefix, i , JACK::Port::Audio); - - if ( r ) - mixer->maybe_auto_connect_output( &aux_audio_output.back() ); - - return r; -} - -bool -Module::add_aux_audio_input( const char *prefix, int i ) -{ - return add_aux_port ( true, prefix, i , JACK::Port::Audio); -} - -bool -Module::add_aux_cv_input( const char *prefix, int i ) -{ - return add_aux_port ( true, prefix, i , JACK::Port::CV); -} - - -/************/ -/* Commands */ -/************/ - -void -Module::command_open_parameter_editor ( void ) -{ - if ( _editor ) - { - _editor->show(); - } - else if ( ncontrol_inputs() && nvisible_control_inputs() ) - { - DMESSAGE( "Opening module parameters for \"%s\"", label() ); - _editor = new Module_Parameter_Editor( this ); - - _editor->show(); - } -} - -void -Module::command_activate ( void ) -{ - bypass( false ); -} - -void -Module::command_deactivate ( void ) -{ - bypass( true ); -} - -void -Module::command_remove ( void ) -{ - if ( is_default() ) - fl_alert( "Default modules may not be deleted." ); - else - { - chain()->remove( this ); - Fl::delete_widget( this ); - } -} diff --git a/mixer/src/Module.H b/mixer/src/Module.H deleted file mode 100644 index 8eebc82..0000000 --- a/mixer/src/Module.H +++ /dev/null @@ -1,578 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include "debug.h" -#include - -#include "Thread.H" - -#include "Loggable.H" -#include "JACK/Port.H" -#include "OSC/Endpoint.H" -#include -#include - -class Chain; -class Module_Parameter_Editor; -class Fl_Menu_; -class Fl_Menu_Button; -class Fl_Button; -class Mixer_Strip; - -class Module : public Fl_Group, public Loggable { - - int _ins; - int _outs; - int _instances; - nframes_t _nframes; - Chain *_chain; - bool _is_default; - - static nframes_t _sample_rate; - static Module *_copied_module_empty; - static char *_copied_module_settings; - - void init ( void ); - - void insert_menu_cb ( const Fl_Menu_ *m ); - static void insert_menu_cb ( Fl_Widget *w, void *v ); - - void menu_cb ( const Fl_Menu_ *m ); - static void menu_cb ( Fl_Widget *w, void *v ); - Fl_Menu_Button & menu ( void ) const; - - bool copy ( void ) const; - void paste_before ( void ); - -protected: - - Module_Parameter_Editor *_editor; - - volatile bool _bypass; - -public: - - virtual nframes_t get_module_latency ( void ) const { return 0; } - - virtual void get_latency ( JACK::Port::direction_e dir, nframes_t *min, nframes_t *max ) const; - virtual void set_latency ( JACK::Port::direction_e dir, nframes_t min, nframes_t max ); - - /* true if this module was added by default and not under normal user control */ - bool is_default ( void ) const { return _is_default; } - void is_default ( bool v ) { _is_default = v; } - - virtual void update ( void ) {} - - virtual void update_tooltip ( void ); - - class Port - { - - /* support multiple connection for audio ports (many to one, one to many, many to many). - control ports only support one to one and one to many. */ - - - /* char *type_names[] = { "Audio", "Control" }; */ - /* char *direction_names[] = { "Input", "Output" }; */ - - void update_connected_port_buffer ( void ) - { - if ( connected() ) - connected_port()->_buf = _buf; - } - - public: - - enum Direction { INPUT, OUTPUT }; - enum Type { AUDIO, CONTROL, AUX_AUDIO }; - - /* hints for control ports (specifically control inputs) */ - struct Hints - { - enum Type { LINEAR, LOGARITHMIC, BOOLEAN, INTEGER }; - - Type type; - bool ranged; - float minimum; - float maximum; - float default_value; - int dimensions; - bool visible; - - Hints ( ) - { - type = LINEAR; - ranged = false; - minimum = 0; - maximum = 1; /* FIXME: totally bogus, but some - * plugins (SWH delays) don't - * provide an upper bound. */ - default_value = 0.0f; - dimensions = 1; - visible = true; - } - }; - - static int osc_control_change_exact ( float v, void *user_data ); - static int osc_control_change_cv ( float v, void *user_data ); - - Hints hints; - - Port ( Module *module, Direction direction, Type type, const char *name = 0 ) - { - _name = name; - _direction = direction; - _type = type; - _buf = 0; - _nframes = 0; - _module = module; - _scaled_signal = 0; - _unscaled_signal = 0; - _by_number_path = 0; - _by_number_number = -1; - _jack_port = 0; - } - - Port ( const Port& p ) - { - _name = p._name; - _direction = p._direction; - _type = p._type; - _buf = p._buf; - _nframes = p._nframes; - _module = p._module; - hints = p.hints; - _scaled_signal = p._scaled_signal; - _unscaled_signal = p._unscaled_signal; - _by_number_path = 0; - _by_number_number = -1; - _jack_port = p._jack_port; - } - - virtual ~Port ( ) - { - if ( _by_number_path ) - free( _by_number_path ); - _by_number_path = NULL; - } - - const char *name ( void ) const { return _name; } - Type type ( void ) const { return _type; } - Direction direction ( void ) const { return _direction; } - - Module * module ( void ) const { return _module; } - nframes_t nframes ( void ) const { return _nframes; } - - void buffer ( void *buf, nframes_t nframes ) { _buf = buf; _nframes = nframes; }; - void *buffer ( void ) const { return _buf; } - - OSC::Signal *scaled_signal ( void ) { return _scaled_signal; } - - int _by_number_number; - char *_by_number_path; - - const char *osc_path ( ) - { - if ( _scaled_signal ) - return _scaled_signal->path(); - else - return NULL; - } - - const char *osc_number_path ( void ); - - void update_osc_port ( ) - { -// if ( INPUT == _direction ) - change_osc_path( generate_osc_path() ); - } - - void destroy_osc_port ( ) - { - delete _unscaled_signal; - delete _scaled_signal; - - _unscaled_signal = _scaled_signal = NULL; - } - - void control_value_no_callback ( float f ) - { - /* can also be called from the OSC thread */ - ASSERT( Thread::is( "UI" ) || Thread::is( "OSC" ), - "Function called from wrong thread! (is %s)", Thread::current()->name() ); - - if ( buffer() ) - { - *((float*)buffer()) = f; - } - } - - void control_value ( float f ) - { - control_value_no_callback( f ); - _module->handle_control_changed( this ); - if ( connected() ) - connected_port()->_module->handle_control_changed( connected_port() ); - } - - float control_value ( void ) const - { - if ( buffer() ) - return *((float*)buffer()); - else - return 0.0f; - } - - bool connected ( void ) const { - if ( _type == Port::AUDIO ) - /* internal audio ports are considered connected by the buffer setting */ - return _buf != 0; - else - /* control and external audio ports belong to a graph */ - return _connected.size() > 0; - } - bool connected_osc ( void ) const; - - Port *connected_port ( void ) const - { - ASSERT( _type == Port::CONTROL, "Operation only available for control ports" ); - return _connected.size() == 0 ? NULL : _connected.front(); - } - - void connect_to ( Port *to ) - { - if ( _type != Port::AUX_AUDIO ) - { - _buf = to->_buf; - } - - if ( jack_port() && to->jack_port() ) - jack_port()->connect( to->jack_port()->jack_name() ); - - if ( std::find(_connected.begin(),_connected.end(),to) == _connected.end() ) - { - _connected.push_back(to); - to->_connected.push_back(this); - } - } - - - /* disconnect this port from any ports of modules belonging to strip /o/ */ - void disconnect_from_strip ( Mixer_Strip *o ); - - void connect_to ( void *buf ) - { - ASSERT( _type == Port::CONTROL, "Operation only available for control ports" ); - _buf = buf; - update_connected_port_buffer(); - } - - void set_buffer ( void *buf ) - { - ASSERT( _type != Port::CONTROL, "Operation only available for audio ports" ); - _buf = buf; - } - - void send_feedback ( void ); - - bool connected_to ( Port *p ) - { - return std::find( _connected.begin(), _connected.end(), p ) != _connected.end(); - } - - /* disconnect from specified port */ - void disconnect ( Port *p ) - { - if ( ! connected_to(p) ) - return; - - if ( _type == Port::CONTROL && p->_module ) - p->_module->handle_control_disconnect( this ); - - if ( jack_port() && p->jack_port() ) - jack_port()->disconnect( p->jack_port()->jack_name() ); - - _connected.remove(p); - p->_connected.remove(this); - } - - /* disconnect from *all* connected ports */ - void disconnect ( void ) - { - if ( _connected.size() ) - { - for ( std::list::iterator i = _connected.begin(); i != _connected.end(); i++ ) - { - Port *p = *i; - - /* iterator about to be invalidated... */ - i = _connected.erase(i); - - disconnect(p); - } - } - } - - void jack_port ( JACK::Port *v ) { _jack_port = v; } - JACK::Port *jack_port ( void ) const { return _jack_port; } - - private: - - char *generate_osc_path ( void ); - void change_osc_path ( char *path ); - - std::list _connected; - Type _type; - Direction _direction; - const char *_name; - void *_buf; - nframes_t _nframes; - Module *_module; - /* used for auxilliary I/Os */ - JACK::Port *_jack_port; - - OSC::Signal *_scaled_signal; - OSC::Signal *_unscaled_signal; - - static void handle_signal_connection_state_changed ( OSC::Signal *, void *o ); - }; - - void bbox ( int &X, int &Y, int &W, int &H ) - { - X += + 5; - Y += 5; - W -= 10; - H -= 10; - } - - Module ( int W, int H, const char *L = 0 ); - Module ( ); - Module ( bool is_default, int W, int H, const char *L = 0 ); - - virtual ~Module ( ); - - LOG_NAME_FUNC( Module ); - - nframes_t nframes ( void ) const { return _nframes; } - virtual void resize_buffers ( nframes_t v ) { _nframes = v; } - - - int instances ( void ) const { return _instances; } - void instances ( int i ) { _instances = i; } - - bool is_being_controlled ( void ) const - { - for ( nframes_t i = control_input.size(); i--; ) - if ( control_input[i].connected() ) - return true; - return false; - } - - bool is_controlling ( void ) const - { - for ( nframes_t i = control_output.size(); i--; ) - if ( control_output[i].connected() ) - return true; - return false; - } - - /* bool */ - /* is_being_controlled_osc ( void ) const */ - /* { */ - /* for ( nframes_t i = control_input.size(); i--; ) */ - /* if ( control_input[i].connected_osc() ) */ - /* return true; */ - /* return false; */ - /* } */ - - virtual const char *name ( void ) const = 0; - virtual const char *basename ( void ) const { return "Module"; } - - std::vector audio_input; - std::vector audio_output; - std::vector control_input; - std::vector control_output; - std::vector aux_audio_input; - std::vector aux_audio_output; - - void add_port ( const Port &p ) - { - if ( p.type() == Port::AUDIO && p.direction() == Port::INPUT ) - audio_input.push_back( p ); - else if ( p.type() == Port::AUDIO && p.direction() == Port::OUTPUT ) - audio_output.push_back( p ); - else if ( p.type() == Port::CONTROL && p.direction() == Port::INPUT ) - control_input.push_back( p ); - else if ( p.type() == Port::CONTROL && p.direction() == Port::OUTPUT ) - control_output.push_back( p ); - } - - int noutputs ( void ) const - { - return audio_output.size(); - } - - int ninputs ( void ) const - { - return audio_input.size(); - } - - int ncontrol_inputs ( void ) const - { - return control_input.size(); - } - - int ncontrol_outputs ( void ) const - { - return control_output.size(); - } - - int nvisible_control_inputs ( void ) const - { - int n = 0; - for ( std::vector::const_iterator i = control_input.begin(); - i != control_input.end(); - i++ ) - if ( i->hints.visible ) - n++; - - return n; - } - - virtual bool bypass ( void ) const { return _bypass; } - virtual void bypass ( bool v ) { _bypass = v; } - - virtual bool bypassable ( void ) const - { - return ninputs() == noutputs() || - ( ninputs() == 1 && noutputs() == 2 ); - } - - int control_input_port_index ( Port *p ) - { - for ( nframes_t i = control_input.size(); i--; ) - if ( &control_input[i] == p ) - return i; - - return -1; - } - - int control_output_port_index ( Port *p ) - { - for ( nframes_t i = control_output.size(); i--; ) - if ( &control_output[i] == p ) - return i; - - return -1; - } - - Chain *chain ( void ) const { return _chain; } - void chain ( Chain * v ); - - char *get_parameters ( void ) const; - void set_parameters ( const char * ); - - bool show_analysis_window ( void ); - - void send_feedback ( void ); - virtual bool initialize ( void ) { return true; } - - /* for the given number of inputs, return how many outputs this - * plugin would have. -1 if this plugin can't support so many - * inputs. */ - virtual int can_support_inputs ( int n ) = 0; - /* called by the chain whenever we need to adjust our input - * channel configuration, but only if can_support_inputs() returns - * true */ - virtual bool configure_inputs ( int n ) = 0; - - virtual void process ( nframes_t ) = 0; - - /* called whenever the module is initialized or when the sample rate is changed at runtime */ - virtual void handle_sample_rate_change ( nframes_t sample_rate ) {} - - /* called whenever the value of a control port is changed. - This can be used to take appropriate action from the GUI thread */ - virtual void handle_control_changed ( Port * ); - virtual void handle_control_disconnect ( Port * ) {} - /* called whenever the name of the chain changes (usually because - * the name of the mixer strip changed). */ - virtual void handle_chain_name_changed (); - - virtual void handle_port_connection_change () {} - - /* module should create a new context, run against this impulse, - * and return true if there's anything worth reporting */ - virtual bool get_impulse_response ( sample_t *buf, nframes_t nframes ) - { - return false; - } - -#define MODULE_CLONE_FUNC(class) \ - virtual Module *clone_empty ( void ) const \ - { \ - return new class (); \ - } - - virtual Module *clone_empty ( void ) const { return NULL; } - Module *clone ( Chain *dest ) const; - Module *clone ( void ) const; - -protected: - - void draw_connections ( void ); - void draw_label ( int X, int Y, int W, int H ); - void draw_box ( int X, int Y, int W, int H ); - - virtual void draw ( void ) { Module::draw_box(x(),y(),w(),h()); Module::draw_label(x(),y(),w(),h()); } - virtual int handle ( int m ); - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - bool add_aux_port ( bool input, const char *prefix, int n , JACK::Port::type_e type ); - -public: - nframes_t sample_rate ( void ) const { return Module::_sample_rate; } - - - void auto_connect_outputs(); - void auto_disconnect_outputs(); - - void freeze_ports ( void ); - void thaw_ports ( void ); - - bool add_aux_audio_output ( const char *prefix, int n ); - bool add_aux_audio_input ( const char *prefix, int n ); - bool add_aux_cv_input ( const char *prefix, int n ); - - static void set_sample_rate ( nframes_t srate ) { _sample_rate = srate; } - - void command_open_parameter_editor(); - virtual void command_activate ( void ); - virtual void command_deactivate ( void ); - virtual void command_remove ( void ); - -}; diff --git a/mixer/src/Module_Parameter_Editor.C b/mixer/src/Module_Parameter_Editor.C deleted file mode 100644 index fbd3e72..0000000 --- a/mixer/src/Module_Parameter_Editor.C +++ /dev/null @@ -1,671 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "FL/Fl_Flowpack.H" -#include "FL/Fl_Labelpad_Group.H" -#include "FL/Fl_Value_SliderX.H" -#include "FL/Fl_DialX.H" -#include -#include "Module.H" -#include "Module_Parameter_Editor.H" -#include "Controller_Module.H" -#include "Chain.H" -#include "Panner.H" -#include -#include "debug.h" -#include - -#include "FL/test_press.H" -#include "FL/menu_popup.H" - - -#include "SpectrumView.H" -#include "string.h" - -bool -Module_Parameter_Editor::is_probably_eq ( void ) -{ - const char *name = _module->label(); - - return strcasestr( name, "eq" ) || - strcasestr( name, "filter" ) || - strcasestr( name, "parametric" ) || - strcasestr( name, "band" ); -} - -Module_Parameter_Editor::Module_Parameter_Editor ( Module *module ) : Fl_Double_Window( 900,240) -{ - _module = module; - _resized = false; - _min_width = 100; - - char lab[256]; - if ( strcmp( module->name(), module->label() ) ) - { - snprintf( lab, sizeof( lab ), "%s : %s", module->name(), module->label() ); - } - else - strcpy( lab, module->label() ); - - char title[512]; - snprintf( title, sizeof( title ), "%s - %s - %s", "Mixer", module->chain()->name(), lab ); - - copy_label( title ); - -// fl_font( FL_HELVETICA, 14 ); - - _min_width = 30 + fl_width( module->label() ); - - { Fl_Group *o = new Fl_Group( 0, 0, w(), 25 ); - o->label( module->label() ); - o->labelfont( 2 ); - o->labeltype( FL_SHADOW_LABEL ); - o->labelsize( 14 ); - o->align( FL_ALIGN_TOP | FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - - { Fl_Menu_Button *o = mode_choice = new Fl_Menu_Button( 0, 0, 25, 25 ); - o->add( "Knobs" ); - o->add( "Horizontal Sliders" ); - o->add( "Vertical Sliders" ); - o->label( NULL ); - o->value( 1 ); - o->when( FL_WHEN_CHANGED ); - o->callback( cb_mode_handle, this ); - } - o->resizable(0); - o->end(); - } - - { Fl_Scroll *o = control_scroll = new Fl_Scroll( 0, 40, w(), h() - 40 ); - { Fl_Group *o = new Fl_Group( 0, 40, w(), h() - 40 ); - { Fl_Flowpack *o = control_pack = new Fl_Flowpack( 50, 40, w() - 100, h() - 40 ); - o->type( FL_HORIZONTAL ); - o->flow( true ); - o->vspacing( 5 ); - o->hspacing( 5 ); - - o->end(); - } - o->resizable( 0 ); - o->end(); - } - o->end(); - } - resizable(control_scroll); - - end(); - - make_controls(); -} - -Module_Parameter_Editor::~Module_Parameter_Editor ( ) -{ -} - - - -void -Module_Parameter_Editor::update_spectrum ( void ) -{ - nframes_t sample_rate = _module->sample_rate(); - - SpectrumView *o = spectrum_view; - - o->sample_rate( sample_rate ); - - nframes_t nframes = sample_rate / 10; - - float *buf = new float[nframes]; - - memset( buf, 0, sizeof(float) * nframes ); - - buf[0] = 1; - - bool show = false; - - if ( ! _module->get_impulse_response( buf, nframes ) ) - show = is_probably_eq(); - else - show = true; - - o->data( buf, nframes ); - - if ( show && ! o->parent()->visible() ) - { - o->parent()->show(); - update_control_visibility(); - } - - o->redraw(); -} - -void -Module_Parameter_Editor::make_controls ( void ) -{ - Module *module = _module; - - control_pack->clear(); - - { SpectrumView *o = spectrum_view = new SpectrumView( 25, 40, 300, 240, "Spectrum" ); - o->labelsize(9); - o->align(FL_ALIGN_TOP); - - - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( (Fl_Widget*)o ); - - flg->hide(); - - control_pack->add( flg ); - } - - - controls_by_port.clear(); - - /* these are for detecting related parameter groups which can be - better represented by a single control */ - azimuth_port_number = -1; - float azimuth_value = 0.0f; - elevation_port_number = -1; - float elevation_value = 0.0f; - radius_port_number = -1; - float radius_value = 0.0f; - - Fl_Color fc = fl_color_add_alpha( FL_CYAN, 200 ); - Fl_Color bc = FL_BACKGROUND2_COLOR; - - controls_by_port.resize( module->control_input.size() ); - - if ( mode_choice->value() == 1 ) - { - control_pack->vspacing( 1 ); - control_pack->hspacing( 10 ); - control_pack->flow(true); - control_pack->flowdown(true); - control_pack->type( FL_HORIZONTAL ); - control_pack->size( 900, 240 ); - } - else if ( mode_choice->value() == 2 ) - { - control_pack->vspacing( 10 ); - control_pack->hspacing( 10 ); - control_pack->flow(true); - control_pack->flowdown(false); - control_pack->type( FL_HORIZONTAL ); - control_pack->size( 900, 250 ); - } - else if ( mode_choice->value() == 0 ) - { - control_pack->vspacing( 10 ); - control_pack->hspacing( 10 ); - control_pack->flow(true); - control_pack->flowdown(true); - control_pack->type( FL_HORIZONTAL ); - control_pack->size( 700, 50 ); - - } - - for ( unsigned int i = 0; i < module->control_input.size(); ++i ) - { - Fl_Widget *w; - - Module::Port *p = &module->control_input[i]; - - /* if ( !p->hints.visible ) */ - /* continue; */ - - if ( !strcasecmp( "Azimuth", p->name() ) && - 180.0f == p->hints.maximum && - -180.0f == p->hints.minimum ) - { - azimuth_port_number = i; - azimuth_value = p->control_value(); - continue; - } - else if ( !strcasecmp( "Elevation", p->name() ) && - 90.0f == p->hints.maximum && - -90.0f == p->hints.minimum ) - { - elevation_port_number = i; - elevation_value = p->control_value(); - continue; - } - else if ( !strcasecmp( "Radius", p->name() ) ) - { - radius_port_number = i; - radius_value = p->control_value(); - continue; - } - - if ( p->hints.type == Module::Port::Hints::BOOLEAN ) - { - Fl_Button *o = new Fl_Button( 0, 0, 24, 24, p->name() ); - w = o; - o->selection_color( fc ); - o->type( FL_TOGGLE_BUTTON ); - o->value( p->control_value() ); - o->align(FL_ALIGN_TOP); - } - else if ( p->hints.type == Module::Port::Hints::INTEGER ) - { - - Fl_Counter *o = new Fl_Counter(0, 0, 58, 24, p->name() ); - w = o; - - o->type(1); - o->step(1); - o->align(FL_ALIGN_TOP); - - if ( p->hints.ranged ) - { - o->minimum( p->hints.minimum ); - o->maximum( p->hints.maximum ); - } - - o->value( p->control_value() ); - - } - else - { - if ( mode_choice->value() == 0 ) - { - Fl_DialX *o = new Fl_DialX( 0, 0, 60, 60, p->name() ); - w = o; - - if ( p->hints.ranged ) - { - DMESSAGE( "Min: %f, max: %f", p->hints.minimum, p->hints.maximum ); - - o->minimum( p->hints.minimum ); - o->maximum( p->hints.maximum ); - } - o->color( bc ); - o->selection_color( fc ); - o->value( p->control_value() ); - o->align(FL_ALIGN_TOP); - o->box( FL_DOWN_BOX ); - - /* a couple of plugins have ridiculously small units */ - float r = fabs( p->hints.maximum - p->hints.minimum ); - - if ( r <= 0.01f ) - o->precision( 4 ); - else if ( r <= 0.1f ) - o->precision( 3 ); - else if ( r <= 100.0f ) - o->precision( 2 ); - else if ( r <= 5000.0f ) - o->precision( 1 ); - /* else if ( r <= 10000.0f ) */ - /* o->precision( 1 ); */ - else - o->precision( 0 ); - - } - else - { - Fl_Value_SliderX *o = new Fl_Value_SliderX( 0, 0, 120, 24, p->name() ); - w = o; - - if ( mode_choice->value() == 1 ) - { - o->type( FL_HORIZONTAL ); - - o->align( FL_ALIGN_RIGHT ); - o->size( 200, 24 ); - if ( p->hints.ranged ) - { - o->minimum( p->hints.minimum ); - o->maximum( p->hints.maximum ); - } - } - else - { - o->type( FL_VERTICAL ); - o->align(FL_ALIGN_TOP); - - o->size( 24, 200 ); - /* have to reverse the meaning of these to get the - * orientation of the slider right */ - o->maximum( p->hints.minimum ); - o->minimum( p->hints.maximum ); - } - if ( p->hints.type & Module::Port::Hints::LOGARITHMIC ) - o->log(true); - - o->precision( 2 ); - /* a couple of plugins have ridiculously small units */ - float r = fabs( p->hints.maximum - p->hints.minimum ); - - if ( r <= 0.01f ) - o->precision( 4 ); - else if ( r <= 0.1f ) - o->precision( 3 ); - else if ( r <= 100.0f ) - o->precision( 2 ); - else if ( r <= 5000.0f ) - o->precision( 1 ); - /* else if ( r <= 10000.0f ) */ - /* o->precision( 1 ); */ - else - o->precision( 0 ); - - o->textsize( 8 ); -// o->box( FL_NO_BOX ); - o->slider( FL_UP_BOX ); - o->color( bc ); - o->selection_color( fc ); - o->value( p->control_value() ); - } - - } -// w->align(FL_ALIGN_TOP); - w->labelsize( 10 ); - - controls_by_port[i] = w; - - w->copy_tooltip( p->osc_path() ); - - _callback_data.push_back( callback_data( this, i ) ); - - if ( p->hints.type == Module::Port::Hints::BOOLEAN ) - w->callback( cb_button_handle, &_callback_data.back() ); - else - w->callback( cb_value_handle, &_callback_data.back() ); - - { - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( w ); - - flg->set_visible_focus(); - - control_pack->add( flg ); - } - - } - - if ( azimuth_port_number >= 0 && elevation_port_number >= 0 ) - { - Panner *o = new Panner( 0,0, 502,502 ); - o->box(FL_FLAT_BOX); - o->color(FL_GRAY0); - o->selection_color(FL_BACKGROUND_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(FL_ALIGN_TOP); - o->when(FL_WHEN_CHANGED); - o->label( "Spatialization" ); - o->labelsize( 10 ); - - _callback_data.push_back( callback_data( this, azimuth_port_number, elevation_port_number, radius_port_number ) ); - o->callback( cb_panner_value_handle, &_callback_data.back() ); - - o->point( 0 )->azimuth( azimuth_value ); - o->point( 0 )->elevation( elevation_value ); - if ( radius_port_number >= 0 ) - { - o->point( 0 )->radius_enabled = true; - o->point( 0 )->radius( radius_value ); - } - - Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( o ); - - flg->resizable(o); - control_pack->add( flg ); - - controls_by_port[azimuth_port_number] = o; - controls_by_port[elevation_port_number] = o; - if ( radius_port_number >= 0 ) - controls_by_port[radius_port_number] = o; - } - - update_spectrum(); - - update_control_visibility(); -} - -void -Module_Parameter_Editor::update_control_visibility ( void ) -{ - for ( unsigned int i = 0; i < _module->control_input.size(); ++i ) - { - const Module::Port *p = &_module->control_input[i]; - - if ( p->hints.visible ) - controls_by_port[i]->parent()->show(); - else - controls_by_port[i]->parent()->hide(); - } - - control_pack->dolayout(); - - int width = control_pack->w() + 100; - int height = control_pack->h() + 60; - - if ( width < _min_width ) - width = _min_width; - - control_pack->parent()->size( control_pack->w() + 100, control_pack->h() ); - - control_scroll->scroll_to(0, 0 ); - - size( width, height ); - size_range( width, height, width, height ); - -} - -void -Module_Parameter_Editor::cb_value_handle ( Fl_Widget *w, void *v ) -{ - callback_data *cd = (callback_data*)v; - - cd->base_widget->set_value( cd->port_number[0], ((Fl_Valuator*)w)->value() ); -} - -void -Module_Parameter_Editor::cb_button_handle ( Fl_Widget *w, void *v ) -{ - callback_data *cd = (callback_data*)v; - - cd->base_widget->set_value( cd->port_number[0], ((Fl_Button*)w)->value() ); -} - - -void -Module_Parameter_Editor::cb_panner_value_handle ( Fl_Widget *w, void *v ) -{ - callback_data *cd = (callback_data*)v; - - cd->base_widget->set_value( cd->port_number[0], ((Panner*)w)->point( 0 )->azimuth() ); - cd->base_widget->set_value( cd->port_number[1], ((Panner*)w)->point( 0 )->elevation() ); - cd->base_widget->set_value( cd->port_number[2], ((Panner*)w)->point( 0 )->radius() ); - -} - -void -Module_Parameter_Editor::cb_mode_handle ( Fl_Widget *, void *v ) -{ - ((Module_Parameter_Editor*)v)->make_controls(); -} - -void -Module_Parameter_Editor::bind_control ( int i ) -{ - Module::Port *p = &_module->control_input[i]; - - if ( p->connected() ) - /* can only bind once */ - return; - - Controller_Module *o = new Controller_Module(); - o->label( p->name() ); - o->chain( _module->chain() ); - o->horizontal( true ); - o->connect_to( p ); - - _module->chain()->add_control( o ); - _module->redraw(); -} - -/* Display changes initiated via automation or from other parts of the GUI */ -void -Module_Parameter_Editor::handle_control_changed ( Module::Port *p ) -{ - int i = _module->control_input_port_index( p ); - - Fl_Widget *w = controls_by_port[i]; - - if ( i == azimuth_port_number || - i == elevation_port_number || - i == radius_port_number ) - { - Panner *_panner = (Panner*)w; - - if ( i == azimuth_port_number ) - _panner->point(0)->azimuth( p->control_value() ); - else if ( i == elevation_port_number ) - _panner->point(0)->elevation( p->control_value() ); - else if ( i == radius_port_number ) - _panner->point(0)->radius( p->control_value() ); - - _panner->redraw(); - - return; - } - - - if ( p->hints.type == Module::Port::Hints::BOOLEAN ) - { - Fl_Button *v = (Fl_Button*)w; - - v->value( p->control_value() ); - } - else - { - Fl_Valuator *v = (Fl_Valuator*)w; - - v->value( p->control_value() ); - } - - update_spectrum(); -} - - -void -Module_Parameter_Editor::reload ( void ) -{ -// make_controls(); - update_control_visibility(); - redraw(); -} - -void -Module_Parameter_Editor::set_value (int i, float value ) -{ - if ( i >= 0 ) - { - _module->control_input[i].control_value( value ); - if ( _module->control_input[i].connected() ) - _module->control_input[i].connected_port()->module()->handle_control_changed( _module->control_input[i].connected_port() ); - } - - update_spectrum(); -// _module->handle_control_changed( &_module->control_input[i] ); -} - -void -Module_Parameter_Editor::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Module_Parameter_Editor*)v)->menu_cb((Fl_Menu_*)w); -} - -void -Module_Parameter_Editor::menu_cb ( Fl_Menu_* m ) -{ - char picked[256]; - - if ( ! m->mvalue() || m->mvalue()->flags & FL_SUBMENU_POINTER || m->mvalue()->flags & FL_SUBMENU ) - return; - - strncpy( picked, m->mvalue()->label(), sizeof( picked ) ); - -// m->item_pathname( picked, sizeof( picked ) ); - - DMESSAGE( "%s", picked ); - - if ( ! strcmp( picked, "Bind" ) ) - { - bind_control( _selected_control ); - } -} - -Fl_Menu_Button & -Module_Parameter_Editor::menu ( void ) const -{ - static Fl_Menu_Button m( 0, 0, 0, 0, "Control" ); - - m.clear(); - - m.add( "Bind", 0, 0, 0, FL_MENU_RADIO | (_module->control_input[_selected_control].connected() ? FL_MENU_VALUE : 0 )); -// m.add( "Unbind", 0, &Module::menu_cb, this, 0, FL_MENU_RADIO ); - - m.callback( menu_cb, (void*)this ); - - return m; -} - -int -Module_Parameter_Editor::handle ( int m ) -{ - switch ( m ) - { - case FL_PUSH: - if ( test_press( FL_BUTTON3 ) ) - { - for ( unsigned int i = 0; i < controls_by_port.size(); i++ ) - { - if ( Fl::event_inside( controls_by_port[i] ) ) - { - _selected_control = i; - - Fl_Menu_Button &m = menu(); - - menu_popup(&m,Fl::event_x(), Fl::event_y()); - - return 1; - } - } - return 0; - } - - } - - return Fl_Group::handle(m); -} diff --git a/mixer/src/Module_Parameter_Editor.H b/mixer/src/Module_Parameter_Editor.H deleted file mode 100644 index ab3f2fb..0000000 --- a/mixer/src/Module_Parameter_Editor.H +++ /dev/null @@ -1,112 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -class Fl_Pack; -class Fl_Flowpack; -class Module; -class Fl_Menu_Button; -class Panner; -class Fl_Scroll; -class SpectrumView; - -#include -#include - -class Module_Parameter_Editor : public Fl_Double_Window -{ - Module *_module; - - struct callback_data - { - Module_Parameter_Editor *base_widget; - - int port_number[3]; - - callback_data ( Module_Parameter_Editor *base_widget, int port_number ) - { - this->base_widget = base_widget; - this->port_number[0] = port_number; - this->port_number[1] = -1; - this->port_number[2] = -1; - } - - callback_data ( Module_Parameter_Editor *base_widget, int port_number1, int port_number2 ) - { - this->base_widget = base_widget; - this->port_number[0] = port_number1; - this->port_number[1] = port_number2; - this->port_number[2] = -1; - } - - callback_data ( Module_Parameter_Editor *base_widget, int port_number1, int port_number2, int port_number3 ) - { - this->base_widget = base_widget; - this->port_number[0] = port_number1; - this->port_number[1] = port_number2; - this->port_number[2] = port_number3; - } - - }; - - void update_control_visibility ( void ); - static void cb_button_handle ( Fl_Widget *w, void *v ); - static void cb_value_handle ( Fl_Widget *w, void *v ); - static void cb_panner_value_handle ( Fl_Widget *w, void *v ); - static void cb_mode_handle ( Fl_Widget *w, void *v ); - static void cb_bound_handle ( Fl_Widget *w, void *v ); - void set_value (int i, float value ); - void bind_control ( int i ); - void make_controls ( void ); - void update_spectrum ( void ); - - bool is_probably_eq ( void ); - - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( Fl_Menu_ *m ); - - SpectrumView *spectrum_view; - Fl_Scroll *control_scroll; - Fl_Flowpack *control_pack; - Fl_Menu_Button *mode_choice; - bool _resized; - int _min_width; - int _selected_control; - - int azimuth_port_number; - int elevation_port_number; - int radius_port_number; - - std::list _callback_data; - std::vector controls_by_port; - - Fl_Menu_Button &menu ( void ) const; - -public: - - void reload ( void ); - void handle_control_changed ( Module::Port *p ); - - int handle ( int m ); - Module_Parameter_Editor ( Module *module ); - virtual ~Module_Parameter_Editor ( ); -}; diff --git a/mixer/src/Mono_Pan_Module.C b/mixer/src/Mono_Pan_Module.C deleted file mode 100644 index 9eac660..0000000 --- a/mixer/src/Mono_Pan_Module.C +++ /dev/null @@ -1,121 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" - -#include -#include - -#include "Mono_Pan_Module.H" - - - -Mono_Pan_Module::Mono_Pan_Module ( ) - : Module ( 50, 24, name() ) -{ - Port p( this, Port::INPUT, Port::CONTROL, "Pan" ); - p.hints.ranged = true; - p.hints.minimum = -1.0f; - p.hints.maximum = 1.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - - end(); - - log_create(); - - smoothing.sample_rate( sample_rate() ); -} - -Mono_Pan_Module::~Mono_Pan_Module ( ) -{ - delete (float*)control_input[0].buffer(); - log_destroy(); -} - - - -void -Mono_Pan_Module::handle_sample_rate_change ( nframes_t n ) -{ - smoothing.sample_rate( n ); -} - -bool -Mono_Pan_Module::configure_inputs ( int ) -{ - return true; -} - - - -/**********/ -/* Engine */ -/**********/ - -void -Mono_Pan_Module::process ( nframes_t nframes ) -{ - if ( unlikely( bypass() ) ) - { - buffer_copy( (sample_t*)audio_output[1].buffer(), (sample_t*)audio_input[0].buffer(), nframes ); - } - else - { - const float gt = (control_input[0].control_value() + 1.0f) * 0.5f; - - sample_t gainbuf[nframes]; - bool use_gainbuf = smoothing.apply( gainbuf, nframes, gt ); - - if ( unlikely( use_gainbuf ) ) - { - /* right channel */ - - buffer_copy_and_apply_gain_buffer( (sample_t*)audio_output[1].buffer(), - (sample_t*)audio_input[0].buffer(), - gainbuf, - nframes ); - - /* left channel */ - for ( nframes_t i = 0; i < nframes; i++ ) - gainbuf[i] = 1.0f - gainbuf[i]; - - buffer_apply_gain_buffer( (sample_t*)audio_output[0].buffer(), gainbuf, nframes ); - } - else - { - /* right channel */ - buffer_copy_and_apply_gain( (sample_t*)audio_output[1].buffer(), - (sample_t*)audio_input[0].buffer(), - nframes, - gt ); - - /* left channel */ - buffer_apply_gain( (sample_t*)audio_output[0].buffer(), nframes, 1.0f - gt); - } - } -} diff --git a/mixer/src/Mono_Pan_Module.H b/mixer/src/Mono_Pan_Module.H deleted file mode 100644 index 7ede987..0000000 --- a/mixer/src/Mono_Pan_Module.H +++ /dev/null @@ -1,49 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" -#include "dsp.h" - -class Mono_Pan_Module : public Module -{ - Value_Smoothing_Filter smoothing; - -public: - - Mono_Pan_Module ( ); - virtual ~Mono_Pan_Module ( ); - - const char *name ( void ) const { return "Mono Pan"; } - - int can_support_inputs ( int n ) { return ( n == 1 ) ? 2 : -1; } - bool configure_inputs ( int n ); - - LOG_CREATE_FUNC( Mono_Pan_Module ); - - MODULE_CLONE_FUNC( Mono_Pan_Module ); - - virtual void handle_sample_rate_change ( nframes_t n ); - -protected: - - virtual void process ( nframes_t nframes ); - -}; diff --git a/mixer/src/NSM.C b/mixer/src/NSM.C deleted file mode 100644 index b1083f6..0000000 --- a/mixer/src/NSM.C +++ /dev/null @@ -1,121 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" -#include "debug.h" -#include "Mixer.H" -#include "NSM.H" -#include "Project.H" - -#include "OSC/Endpoint.H" - -extern char *instance_name; -extern Mixer *mixer; - -extern NSM_Client *nsm; - -NSM_Client::NSM_Client ( ) -{ -} - -int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); -int command_save ( char **out_msg ); - -int -NSM_Client::command_broadcast ( const char *path, lo_message msg ) -{ -// int argc = lo_message_get_argc( msg ); -// lo_arg **argv = lo_message_get_argv( msg ); - - if ( !strcmp( path, "/non/hello" ) ) - { - mixer->handle_hello( msg ); - return 0; - } - else - return -1; - -} - - -int -NSM_Client::command_save ( char **out_msg ) -{ - Fl::lock(); - - int r = ERR_OK; - - if ( ! mixer->command_save() ) - { - *out_msg = strdup( "Failed to save for unknown reason"); - return r = ERR_GENERAL; - } - - Fl::unlock(); - - return r; -} - -int -NSM_Client::command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ) -{ - Fl::lock(); - - if ( instance_name ) - free( instance_name ); - - instance_name = strdup( client_id ); - - mixer->osc_endpoint->name( client_id ); - - int r = ERR_OK; - - if ( Project::validate( name ) ) - { - if ( ! mixer->command_load( name, display_name ) ) - { - *out_msg = strdup( "Failed to load for unknown reason" ); - r = ERR_GENERAL; - } - } - else - { - if ( ! mixer->command_new( name, display_name ) ) - { - *out_msg = strdup( "Failed to load for unknown reason" ); - r = ERR_GENERAL; - } - } - - mixer->say_hello(); - - Fl::unlock(); - - return r; -} - -void -NSM_Client::command_active ( bool active ) -{ - Fl::lock(); - - mixer->sm_active( active ); - - Fl::unlock(); -} diff --git a/mixer/src/NSM.H b/mixer/src/NSM.H deleted file mode 100644 index b289c00..0000000 --- a/mixer/src/NSM.H +++ /dev/null @@ -1,40 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "NSM/Client.H" - -class NSM_Client : public NSM::Client -{ - -public: - - NSM_Client ( ); - ~NSM_Client ( ) { }; - -protected: - - int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); - int command_save ( char **out_msg ); - - void command_active ( bool active ); - - int command_broadcast ( const char *path, lo_message msg ); -}; diff --git a/mixer/src/Panner.C b/mixer/src/Panner.C deleted file mode 100644 index c48e852..0000000 --- a/mixer/src/Panner.C +++ /dev/null @@ -1,553 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Panner.H" -#include -#include -#include -#include -// #include - -#include -#include - -#include "debug.h" - -/* 2D Panner widget. Supports various multichannel configurations. */ - -Panner::Point *Panner::drag; -int Panner::_range_mode = 1; -int Panner::_projection_mode = 0; - -Panner::Panner ( int X, int Y, int W, int H, const char *L ) : - Fl_Group( X, Y, W, H, L ) -{ - _bg_image = 0; - _bg_image_scaled = 0; - _bg_image_projection = 0; -// _projection = POLAR; - _points.push_back( Point( 1, 0 ) ); - - static float ranges[] = { 1,3,5,10,15 }; - { Fl_Choice *o = _range_choice = new Fl_Choice(X + 40,Y + H - 18,75,18,"Range:"); - o->box(FL_UP_FRAME); - o->down_box(FL_DOWN_FRAME); - o->textsize(9); - o->labelsize(9); - o->align(FL_ALIGN_LEFT); - o->add("1 Meter",0,0,&ranges[0]); - o->add("3 Meters",0,0,&ranges[1]); - o->add("5 Meters",0,0,&ranges[2]); - o->add("10 Meters",0,0,&ranges[3]); - o->add("15 Meters",0,0,&ranges[4]); - o->value(_range_mode); - o->callback( cb_mode, this ); - } - - { Fl_Choice *o = _projection_choice = new Fl_Choice(X + W - 75,Y + H - 18,75,18,"Projection:"); - o->box(FL_UP_FRAME); - o->down_box(FL_DOWN_FRAME); - o->textsize(9); - o->labelsize(9); - o->align(FL_ALIGN_LEFT); - o->add("Spherical"); - o->add("Planar"); - o->value(_projection_mode); - o->callback( cb_mode, this ); - } - - end(); -} - -Panner::~Panner ( ) -{ - if ( _bg_image ) - { - if ( _bg_image_scaled ) - delete _bg_image; - else - ((Fl_Shared_Image*)_bg_image)->release(); - } -} - -static int find_numeric_menu_item( const Fl_Menu_Item *menu, int n ) -{ - for ( unsigned int i = 0; menu[i].text; i++ ) - { - if ( atoi( menu[i].text ) == n ) - return i; - } - - return -1; -} - -void -Panner::cb_mode ( Fl_Widget *w, void *v ) -{ - ((Panner*)v)->cb_mode( w ); -} - -void -Panner::cb_mode ( Fl_Widget *w ) -{ - if ( w == _range_choice ) - _range_mode = _range_choice->value(); - else if ( w == _projection_choice ) - _projection_mode = _projection_choice->value(); -} - -void -Panner::range ( float v ) -{ - int i = find_numeric_menu_item( _range_choice->menu(), v ); - - _range_choice->value( i ); - - _range_mode = i; -} - -/** set X, Y, W, and H to the bounding box of point /p/ in screen coords */ -void -Panner::point_bbox ( const Point *p, int *X, int *Y, int *W, int *H ) const -{ - int tx, ty, tw, th; - - bbox( tx, ty, tw, th ); - - float px, py; - float s = 1.0f; - - if ( projection() == POLAR ) - { - project_polar( p, &px, &py, &s ); - } - else - { - project_ortho( p, &px, &py, &s ); - } - - const float htw = float(tw)*0.5f; - const float hth = float(th)*0.5f; - - - *W = *H = tw * s; - - if ( *W < 8 ) - *W = 8; - if ( *H < 8 ) - *H = 8; - - *X = tx + (htw * px + htw) - *W/2; - *Y = ty + (hth * py + hth) - *H/2; - -} - -Panner::Point * -Panner::event_point ( void ) -{ - for ( int i = _points.size(); i--; ) - { - - int px, py, pw, ph; - - Point *p = &_points[ i ]; - - if ( ! p->visible ) - continue; - - point_bbox( p, &px, &py, &pw, &ph ); - -// printf( "%d, %d -- %d %d %d %d\n", Fl::event_x(), Fl::event_y(), px, py, pw, ph ); - - if ( Fl::event_inside( px, py, pw, ph ) ) - return p; - } - - return NULL; -} - - -void -Panner::draw_the_box ( int tx, int ty, int tw, int th ) -{ - draw_box(); - - Fl_Image *i = 0; - - if ( _bg_image && ( _bg_image->h() != th || projection() != _bg_image_projection ) ) - { - if ( _bg_image_scaled ) - delete _bg_image; - else - ((Fl_Shared_Image*)_bg_image)->release(); - - _bg_image = 0; - } - - if ( ! _bg_image ) - { - if ( projection() == POLAR ) - { - if ( th <= 92 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-sphere-92x92.png" ); - else if ( th <= 502 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-sphere-502x502.png" ); - else if ( th <= 802 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-sphere-802x802.png" ); - } - else - { - if ( th <= 92 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-plane-92x92.png" ); - else if ( th <= 502 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-plane-502x502.png" ); - else if ( th <= 802 ) - i = Fl_Shared_Image::get( PIXMAP_PATH "/non-mixer/panner-plane-802x802.png" ); - } - - if ( i && i->h() != th ) - { - Fl_Image *scaled = i->copy( th, th ); - - _bg_image = scaled; - _bg_image_scaled = true; - } - else - { - _bg_image = i; - _bg_image_scaled = false; - } - } - - _bg_image_projection = projection(); - - if ( _bg_image ) - _bg_image->draw( tx, ty ); -} - -/** translate angle /a/ into x/y coords and place the result in /X/ and /Y/ */ -void -Panner::project_polar ( const Point *p, float *X, float *Y, float *S ) const -{ - float xp = 0.0f; - float yp = 0.0f; - float zp = 8.0f; - - float x = 0 - p->y; - float y = 0 - p->x; - float z = 0 - p->z; - - x /= range(); - y /= range(); - z /= range(); - - *X = ((x-xp) / (z + zp)) * (zp); - *Y = ((y-yp) / (z + zp)) * (zp); - *S = (0.025f / (z + zp)) * (zp); -} - -/** translate angle /a/ into x/y coords and place the result in /X/ and /Y/ */ -void -Panner::project_ortho ( const Point *p, float *X, float *Y, float *S ) const -{ - const float x = ( 0 - p->y ) / range(); - const float y = ( 0 - p->x ) / range(); -// const float z = p->z; - -// float zp = 4.0f; - - *X = x; - *Y = y; - - *S = 0.025f; -} - - -void -Panner::set_ortho ( Point *p, float x, float y ) -{ - y = 0 - y; - - y *= 2; - x *= 2; - - p->x = (y) * range(); - p->y = (0 - x) * range(); -} - -void -Panner::set_polar ( Point *p, float x, float y ) -{ - /* FIXME: not quite the inverse of the projection... */ - x = 0 - x; - y = 0 - y; - x *= 2; - y *= 2; - - float r = powf( x,2 ) + powf(y,2 ); - float X = ( 2 * x ) / ( 1 + r ); - float Y = ( 2 * y ) / ( 1 + r ); - float Z = ( -1 + r ) / ( 1 + r ); - - float S = p->radius() / range(); - - X *= S; - Y *= S; - Z *= S; - - p->azimuth( -atan2f( X,Y ) * ( 180 / M_PI ) ); - - if ( p->elevation() > 0.0f ) - p->elevation( -atan2f( Z, sqrtf( powf(X,2) + powf( Y, 2 ))) * ( 180 / M_PI ) ); - else - p->elevation( atan2f( Z, sqrtf( powf(X,2) + powf( Y, 2 ))) * ( 180 / M_PI ) ); -} - - - -void -Panner::set_polar_radius ( Point *p, float x, float y ) -{ - y = 0 - y; - - float r = sqrtf( powf( y, 2 ) + powf( x, 2 ) ); - - if ( r > 1.0f ) - r = 1.0f; - - r *= range() * 2; - - if ( r > range() ) - r = range(); - - p->radius( r ); -} - -void -Panner::draw ( void ) -{ - int tw, th, tx, ty; - - bbox( tx, ty, tw, th ); - - fl_push_clip( x(),y(),w(),h() ); - - draw_the_box( tx, ty, tw, th ); - -// draw_box(); - draw_label(); - - /* if ( _bypassed ) */ - /* { */ - /* draw_box(); */ - /* fl_color( 0 ); */ - /* fl_font( FL_HELVETICA, 12 ); */ - /* fl_draw( "(bypass)", x(), y(), w(), h(), FL_ALIGN_CENTER ); */ - /* goto done; */ - /* } */ - - /* tx += b; */ - /* ty += b; */ - /* tw -= b * 2; */ - /* th -= b * 2; */ - - fl_line_style( FL_SOLID, 1 ); - - fl_color( FL_WHITE ); - - for ( unsigned int i = 0; i < _points.size(); i++ ) - { - Point *p = &_points[i]; - - if ( ! p->visible ) - continue; - - Fl_Color c = fl_color_add_alpha( p->color, 100 ); - - fl_color(c); - - int px, py, pw, ph; - point_bbox( p, &px, &py, &pw, &ph ); - - { - float po = 5; - - fl_push_clip( px - ( po * 12 ), - py - ( po * 12 ), - pw + ( po * 24 ), ph + (po * 24 )); - - fl_pie( px + 5, py + 5, pw - 10, ph - 10, 0, 360 ); - - - fl_pie( px, py, pw, ph, 0, 360 ); - - fl_pop_clip(); - - if ( projection() == POLAR ) - { - - fl_color( fl_color_average( fl_rgb_color( 127,127,127 ), p->color, 0.50 ) ); - fl_begin_loop(); - fl_circle( tx + tw/2, ty + th/2, tw/2.0f * ( ( p->radius() / range() ))); - fl_end_loop(); - } - - } - - const char *s = p->label; - - fl_color( fl_color_add_alpha( fl_rgb_color( 220,255,255 ), 127 ) ); - fl_font( FL_HELVETICA_BOLD_ITALIC, 10 ); - fl_draw( s, px + 20, py + 1, 50, ph - 1, FL_ALIGN_LEFT ); - - if ( tw > 100 ) - { - char pat[50]; - snprintf( pat, sizeof(pat), "%.1f°:%.1f° %.1fm", p->azimuth(), p->elevation(), p->radius() ); - -// fl_color( fl_color_add_alpha( fl_rgb_color( 220,255,255 ), 127 ) ); - fl_font( FL_COURIER, 9 ); - - fl_draw( pat, px + 20, py + 15, 50, ph - 1, FL_ALIGN_LEFT | FL_ALIGN_WRAP ); - - /* fl_font( FL_HELVETICA_ITALIC, 9 ); */ - /* snprintf(pat, sizeof(pat), "range: %.1f meters", range() ); */ - /* fl_draw( pat, tx, ty, tw, th, FL_ALIGN_LEFT | FL_ALIGN_BOTTOM | FL_ALIGN_INSIDE ); */ - - /* if ( _projection == POLAR ) */ - /* { */ - /* fl_draw( "Polar perspective; azimuth, elevation and radius input. Right click controls radius.", tx, ty, tw, th, FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); */ - /* } */ - /* else */ - /* { */ - /* fl_draw( "Polar orthographic; angle and distance input.", tx, ty, tw, th, FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); */ - /* } */ - } - - } - - if ( tw > 200 ) - draw_children(); - - fl_line_style( FL_SOLID, 0 ); - - fl_pop_clip(); -} - -/* return the current gain setting for the path in/out */ -Panner::Point * -Panner::point( int i ) -{ - return &_points[ i ]; -} - -int -Panner::handle ( int m ) -{ - int r = Fl_Group::handle( m ); - - switch ( m ) - { - case FL_ENTER: - case FL_LEAVE: - _projection_choice->value(_projection_mode); - _range_choice->value(_range_mode); - redraw(); - return 1; - case FL_PUSH: - { - if ( Fl::event_button1() || Fl::event_button3() ) - drag = event_point(); - - if ( Fl::event_button2() ) - { - /* if ( _projection == POLAR ) */ - /* _projection = ORTHO; */ - /* else */ - /* _projection = POLAR; */ - } - return 1; - } - case FL_RELEASE: - if ( drag ) - { - do_callback(); - drag = NULL; - redraw(); - return 1; - } - else - return 0; - case FL_MOUSEWHEEL: - { -/* Point *p = event_point(); */ - -/* if ( p ) */ -/* drag = p; */ - -/* if ( drag ) */ -/* { */ -/* // drag->elevation( drag->elevation() + Fl::event_dy()); */ -/* drag->elevation( 0 - drag->elevation() ); */ -/* do_callback(); */ -/* redraw(); */ -/* return 1; */ -/* } */ - - return 1; - } - case FL_DRAG: - { - if ( ! drag ) - return 0; - - int tx, ty, tw, th; - bbox( tx, ty, tw, th ); - - float X = (float(Fl::event_x() - tx) / tw ) - 0.5f; - float Y = (float(Fl::event_y() - ty) / th) - 0.5f; - - if ( Fl::event_button1() ) - { - if ( POLAR == projection() ) - set_polar( drag,X,Y ); - else - { - if ( fabsf( X ) < 0.5f && - fabsf( Y ) < 0.5f ) - set_ortho( drag, X,Y ); - } - } - else - set_polar_radius( drag,X,Y ); - - if ( when() & FL_WHEN_CHANGED ) - do_callback(); - - damage(FL_DAMAGE_EXPOSE); - - return 1; - } - - } - - return r; - -// return 0; -} diff --git a/mixer/src/Panner.H b/mixer/src/Panner.H deleted file mode 100644 index 8bb8e5e..0000000 --- a/mixer/src/Panner.H +++ /dev/null @@ -1,209 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -using namespace std; - -class Panner : public Fl_Group -{ - Fl_Choice *_range_choice; - Fl_Choice *_projection_choice; - - Fl_Image *_bg_image; - bool _bg_image_scaled; - int _bg_image_projection; - - void draw_grid( int,int,int,int); - void draw_the_box( int, int, int, int ); - - static int _range_mode; - static int _projection_mode; - -public: - - struct Point - { - float x,y,z; - - const char *label; - void *userdata; - Fl_Color color; - bool visible; - bool radius_enabled; - - Point ( ) { - x = 1; - y = 0; - z = 0; - label = 0; - visible = 1; - color = FL_WHITE; - radius_enabled = false; - } - - Point ( float D, float A ) - { - radius( D ); - azimuth( A ); - label = 0; - visible = 1; - color = FL_WHITE; - radius_enabled = false; - } - - static inline void spherical_to_cartesian (float a, float e, float &x, float &y, float &z ) - { - a *= M_PI / 180.0f; - e *= M_PI / 180.0f; - - z = sinf(e); - const float ce = cosf(e); - x = ce * cosf(-a); - y = ce * sinf(-a); - } - - float azimuth ( void ) const { - return -atan2f( y,x ) * ( 180 / M_PI ); - } - float elevation ( void ) const { - return atan2f(z,sqrtf(powf(x,2)+powf(y,2)) ) * ( 180 / M_PI ); - } - float radius ( void ) const { - if ( ! radius_enabled ) - return 1.0f; - else - return sqrtf(powf(x,2)+powf(y,2)+powf(z,2)); - } - - void azimuth ( float v ) - { - float r = radius(); - - spherical_to_cartesian( v, elevation(), x,y,z ); - x *= r; - y *= r; - z *= r; - } - - void elevation ( float v ) - { - float r = radius(); - - spherical_to_cartesian( azimuth(), v, x,y,z ); - x *= r; - y *= r; - z *= r; - } - - - void radius ( float v ) - { - if (! radius_enabled ) - return; - - float r = v; - - spherical_to_cartesian( azimuth(), elevation(), x,y,z ); - - x *= r; - y *= r; - z *= r; - } - }; - -private: - - vector _points; - - static int _configs[][12]; - - void bbox ( int &X, int &Y, int &W, int &H ) const - { - W = w() - Fl::box_dw( box() ); - H = h() - Fl::box_dh( box() ); - X = x() + Fl::box_dx( box() ); - Y = y() + Fl::box_dy( box() ); - - int S = W > H ? H : W; - - if ( W > H ) - X += ( (W/2) - (S/2) ); - else if ( H > W ) - Y += ( (H/2) - (S/2) ); - - W = H = S; - } - - void point_bbox ( const Point *p, int *X, int *Y, int *W, int *H ) const; - - Point * event_point ( void ); - Point angle_to_axes ( float a ); - - static Point * drag; - - void set_polar ( Point *p, float x, float y ); - void set_ortho ( Point *p, float x, float y ); - void set_polar_radius ( Point *p, float x, float y ); - void project_polar ( const Point *p, float *X, float *Y, float *S ) const; - void project_ortho ( const Point *p, float *X, float *Y, float *S ) const; - - static void cb_mode ( Fl_Widget *w, void *v ); - void cb_mode ( Fl_Widget *w ); - -protected: - - virtual void draw ( void ); - virtual int handle ( int ); - -public: - - enum { POLAR, ORTHO }; - - int projection ( void ) const { return _projection_mode; } - void projection ( int v ) { _projection_choice->value(v); _projection_mode = v; } - - Panner ( int X, int Y, int W, int H, const char *L = 0 ); - - float range ( void ) const { return *((float*)_range_choice->menu()[_range_mode].user_data()); } - void range ( float v ); - - void clear_points ( void ) { _points.clear(); } - - void add_point( Panner::Point &p ) - { - _points.push_back( p ); - } - - virtual ~Panner ( ); - - Panner::Point *point ( int i ); - - int points ( void ) const { return _points.size(); } - - Panner::Point *pushed ( void ) { return drag; } - -}; diff --git a/mixer/src/Plugin_Chooser.C b/mixer/src/Plugin_Chooser.C deleted file mode 100644 index ea50226..0000000 --- a/mixer/src/Plugin_Chooser.C +++ /dev/null @@ -1,442 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include -#include -#include "Plugin_Chooser_UI.H" -#include "Plugin_Module.H" -#include "Plugin_Chooser.H" -#include "stdio.h" -#include -#include - -#include - -static std::vector _plugin_rows; - -unsigned long -Plugin_Chooser::plugin_chooser ( int ninputs ) -{ - Plugin_Chooser *o = new Plugin_Chooser( 0,0,735,500,"Plugin Chooser"); - - o->ui->inputs_input->value( ninputs ); - - o->search( "", "", "Any", ninputs, 0, o->ui->favorites_button->value() ); - - o->show(); - - while ( o->shown() ) - Fl::wait(); - - unsigned long picked = o->value(); - - delete o; - - return picked; -} - -void -Plugin_Chooser::search ( const char *name, const char *author, const char *category, int ninputs, int noutputs, bool favorites ) -{ - _plugin_rows.clear(); - - for ( std::list::iterator i = _plugins.begin(); i != _plugins.end(); i++ ) - { - Plugin_Module::Plugin_Info *p = &(*i); - - if ( strcasestr( p->name.c_str(), name ) && - strcasestr( p->author.c_str(), author ) ) - { - if ( ! - ((( ( ninputs == 0 || ninputs == p->audio_inputs || ( ninputs == 1 && p->audio_inputs == 2 ) ) ) && - ( noutputs == 0 || noutputs == p->audio_outputs )) || - ( p->audio_inputs == 1 && p->audio_outputs == 1 ) ) ) - continue; - - if ( p->audio_outputs == 0 || p->audio_inputs == 0 ) - /* we don't support these */ - continue; - - if ( favorites > 0 && ! p->favorite ) - continue; - - if ( strcmp( category, "Any" ) ) - { - if ( !p->category.c_str() && strcmp( category, "Unclassified" )) - continue; - - if (strncmp( p->category.c_str(), category, strlen( category ))) - continue; - } - - _plugin_rows.push_back( p ); - } - } - - ui->table->rows( _plugin_rows.size() ); -} - -void -Plugin_Chooser::cb_handle ( Fl_Widget *w, void *v ) -{ - ((Plugin_Chooser*)v)->cb_handle( w ); -} - -void -Plugin_Chooser::cb_handle ( Fl_Widget *w ) -{ - if ( w == ui->all_button ) - { - ui->favorites_button->value( !ui->all_button->value() ); - } - - { - char picked[512]; - ui->category_choice->item_pathname( picked, sizeof( picked ) ); - - search( ui->name_input->value(), - ui->author_input->value(), - picked[0] == '/' ? &picked[1] : picked, - ui->inputs_input->value(), - ui->outputs_input->value(), - ui->favorites_button->value() ); - } -} - -class Plugin_Table : public Fl_Table_Row -{ -protected: - void draw_cell(TableContext context, // table cell drawing - int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0); -public: - Plugin_Table(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l) - { - end(); - } - ~Plugin_Table() { } -}; - -void Plugin_Table::draw_cell(TableContext context, - int R, int C, int X, int Y, int W, int H) -{ - const char *headings[] = { "Fav.", "Name", "Author", "Type", "In", "Out" }; - - static char s[40]; - - switch ( context ) - { - case CONTEXT_STARTPAGE: - fl_font(FL_HELVETICA, 12); - return; - - case CONTEXT_COL_HEADER: - fl_push_clip(X, Y, W, H); - { - fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color()); - fl_color(FL_FOREGROUND_COLOR); - fl_draw(headings[C], X, Y, W, H, FL_ALIGN_CENTER); - } - fl_pop_clip(); - return; - - case CONTEXT_ROW_HEADER: - return; - - case CONTEXT_CELL: - { - fl_font(FL_HELVETICA, 12); - - const char *s2 = (char*)s; - Fl_Align a = FL_ALIGN_CENTER; - int symbol = 0; - Fl_Color c = FL_FOREGROUND_COLOR; - switch ( C ) - { - case 0: - sprintf( s, "%s", "@circle" ); - c = _plugin_rows[R]->favorite ? FL_LIGHT2 : FL_BLACK; - symbol = 1; - fl_font(FL_HELVETICA, 9 ); - break; - case 1: - a = FL_ALIGN_LEFT; - s2 = _plugin_rows[R]->name.c_str(); - break; - case 2: - a = FL_ALIGN_LEFT; - s2 = _plugin_rows[R]->author.c_str(); - break; - case 3: - s2 = _plugin_rows[R]->type; - break; - case 4: - sprintf( s, "%i", _plugin_rows[R]->audio_inputs ); - break; - case 5: - sprintf( s, "%i", _plugin_rows[R]->audio_outputs ); - break; - } - - fl_color( row_selected(R) ? selection_color() : FL_DARK1); - fl_rectf(X, Y, W, H); - fl_color(color()); - fl_rect(X, Y, W, H); - - X+=4; - W-=8; - Y+=4; - H-=8; - - fl_push_clip(X, Y, W, H); - - fl_color(c); - fl_draw(s2, X, Y, W, H, a, 0, symbol ); - - fl_pop_clip(); - return; - } - - case CONTEXT_TABLE: - fprintf(stderr, "TABLE CONTEXT CALLED\n"); - return; - - case CONTEXT_ENDPAGE: - case CONTEXT_RC_RESIZE: - case CONTEXT_NONE: - return; - } -} - -void -Plugin_Chooser::cb_table ( Fl_Widget *w, void *v ) -{ - ((Plugin_Chooser*)v)->cb_table(w); -} - -void -Plugin_Chooser::cb_table ( Fl_Widget *w ) -{ - Fl_Table_Row *o = (Fl_Table_Row*)w; - - int R = o->callback_row(); - int C = o->callback_col(); - - Fl_Table::TableContext context = o->callback_context(); - - if ( context == Fl_Table::CONTEXT_CELL ) - { - if ( C == 0 ) - { - _plugin_rows[R]->favorite = ! _plugin_rows[R]->favorite; - o->redraw(); - } - else - { - _value = _plugin_rows[R]->id; - hide(); - } - } -} - -extern char *user_config_dir; - -static FILE *open_favorites( const char *mode ) -{ - char *path; - - asprintf( &path, "%s/%s", user_config_dir, "favorite_plugins" ); - - FILE *fp = fopen( path, mode ); - - free( path ); - - return fp; -} - -int -Plugin_Chooser::load_favorites ( void ) -{ - FILE *fp = open_favorites( "r" ); - - if ( !fp ) - { - return 0; - } - - unsigned long id; - char *type; - int favorites = 0; - - while ( 2 == fscanf( fp, "%m[^:]:%lu\n", &type, &id ) ) - { - for ( std::list::iterator i = _plugins.begin(); - i != _plugins.end(); - i++ ) - { - if ( !strcmp( (*i).type, type ) && - (*i).id == id ) - { - (*i).favorite = 1; - - favorites++; - } - } - - free(type); - } - - fclose(fp); - - return favorites; -} - -void -Plugin_Chooser::save_favorites ( void ) -{ - FILE *fp = open_favorites( "w" ); - - if ( !fp ) - return; - - for ( std::list::iterator i = _plugins.begin(); - i != _plugins.end(); - i++ ) - { - if ( (*i).favorite ) - { - fprintf( fp, "%s:%lu\n", i->type, i->id ); - } - } - - fclose( fp ); -} - -void -Plugin_Chooser::load_categories ( void ) -{ - ui->category_choice->add( "Any" ); - - std::list categories; - - for ( std::list::iterator i = _plugins.begin(); - i != _plugins.end(); - i++ ) - { - if ( i->category.c_str() ) - { - categories.push_back(i->category); - } - } - - categories.sort(); - - - for ( std::list::const_iterator i = categories.begin(); - i != categories.end(); - i++ ) - { - ui->category_choice->add( i->c_str() ); - } - - ui->category_choice->value( 0 ); -} - -Plugin_Chooser::Plugin_Chooser ( int X,int Y,int W,int H, const char *L ) - : Fl_Double_Window ( X,Y,W,H,L ) -{ - set_modal(); - _value = 0; - - _plugins = Plugin_Module::get_all_plugins(); - - - { - Plugin_Chooser_UI *o = ui = new Plugin_Chooser_UI(X,Y,W,H); - - o->name_input->callback( &Plugin_Chooser::cb_handle, this ); - o->name_input->when( FL_WHEN_CHANGED ); - - - o->author_input->callback( &Plugin_Chooser::cb_handle, this ); - o->author_input->when( FL_WHEN_CHANGED ); - - - o->inputs_input->callback( &Plugin_Chooser::cb_handle, this ); - o->inputs_input->when( FL_WHEN_CHANGED ); - - o->outputs_input->callback( &Plugin_Chooser::cb_handle, this ); - o->outputs_input->when( FL_WHEN_CHANGED ); - - o->favorites_button->callback( &Plugin_Chooser::cb_handle, this ); - o->favorites_button->when( FL_WHEN_CHANGED ); - - o->all_button->callback( &Plugin_Chooser::cb_handle, this ); - o->all_button->when( FL_WHEN_CHANGED ); - - - o->category_choice->callback( &Plugin_Chooser::cb_handle, this ); - o->category_choice->when( FL_WHEN_CHANGED ); - - { - Plugin_Table *o = new Plugin_Table(ui->table->x(),ui->table->y(),ui->table->w(),ui->table->h() ); - ui->table_group->add(o); - ui->table_group->resizable(o); - delete ui->table; - ui->table = o; - /* ui->scalepack->add( o ); */ - /* ui->scalepack->resizable( o ); */ - o->col_header(1); - o->col_resize(1); - o->row_resize(1); - o->cols(6); - o->col_resize_min(4); - o->col_width(0,30); - o->col_width(1,350 - 7); - o->col_width(2,200); - o->col_width(3,75); - o->col_width(4,30); - o->col_width(5,30); - o->color(FL_BLACK); - o->box(FL_NO_BOX); - o->when(FL_WHEN_CHANGED); - o->callback( &Plugin_Chooser::cb_table, this ); - - } - - resizable(o); - } - size_range( 735, 300, 735, 0 ); - - end(); - - load_categories(); - - if ( load_favorites() ) - { - ui->all_button->value(0); - ui->favorites_button->value(1); - } -} - -Plugin_Chooser::~Plugin_Chooser( ) -{ - save_favorites(); -} diff --git a/mixer/src/Plugin_Chooser.H b/mixer/src/Plugin_Chooser.H deleted file mode 100644 index ce67564..0000000 --- a/mixer/src/Plugin_Chooser.H +++ /dev/null @@ -1,58 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include "Plugin_Module.H" -#include - -class Plugin_Chooser_UI; -class Plugin_Chooser : public Fl_Double_Window -{ - Plugin_Chooser_UI *ui; - - std::list _plugins; - - static void cb_handle ( Fl_Widget *w, void *v ); - void cb_handle ( Fl_Widget *w ); - static void cb_table ( Fl_Widget *w, void *v ); - void cb_table ( Fl_Widget *w ); - - void search ( const char *name, const char *author, const char *category, int ninputs, int noutputs, bool favorites ); - - unsigned long _value; - - int load_favorites ( void ); - - void save_favorites ( void ); - - void load_categories ( void ); -public: - - unsigned long value ( void ) const { return _value; } - - Plugin_Chooser ( int X,int Y,int W,int H, const char *L=0 ); - - virtual ~Plugin_Chooser( ); - - static unsigned long plugin_chooser ( int ninputs ); -}; - - diff --git a/mixer/src/Plugin_Chooser_UI.fl b/mixer/src/Plugin_Chooser_UI.fl deleted file mode 100644 index 811242d..0000000 --- a/mixer/src/Plugin_Chooser_UI.fl +++ /dev/null @@ -1,68 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.h} -code_name {.cxx} -decl {\#include } {public global -} - -decl {\#include } {public global -} - -widget_class Plugin_Chooser_UI { - label {Plugin Selector} open - xywh {825 389 735 500} type Double resizable size_range {740 0 740 0} visible -} { - Fl_Group {} {open - xywh {10 5 155 20} - } { - Fl_Round_Button all_button { - label {&All} - xywh {10 5 50 20} type Radio down_box ROUND_DOWN_BOX shortcut 0x80061 value 1 - } - Fl_Round_Button favorites_button { - label {&Favorites} - xywh {65 5 100 20} type Radio down_box ROUND_DOWN_BOX shortcut 0x80066 - } - } - Fl_Group {} {open - xywh {5 29 725 77} box UP_FRAME - code0 {o->resizable(0);} - } { - Fl_Input name_input { - label {Name:} selected - xywh {75 38 300 24} labelsize 12 textsize 13 - } - Fl_Input author_input { - label {Author:} - xywh {435 39 210 22} labelsize 12 textsize 13 - } - Fl_Value_Input outputs_input { - label {Outputs:} - xywh {693 70 30 24} labelsize 12 - } - Fl_Value_Input inputs_input { - label {Inputs:} - xywh {693 39 30 24} labelsize 12 - } - Fl_Choice category_choice { - label {Category:} open - xywh {75 70 405 24} down_box BORDER_BOX labelsize 12 textsize 12 - } {} - } - Fl_Group table_group {open - xywh {5 115 725 380} resizable - } { - Fl_Table table {open - xywh {5 115 725 380} resizable - } {} - } - Fl_Choice type_choice { - label {Type:} open - xywh {530 70 95 24} down_box BORDER_BOX labelsize 12 textsize 12 - } { - MenuItem {} { - label LADSPA - xywh {0 -68 34 18} - } - } -} diff --git a/mixer/src/Plugin_Module.C b/mixer/src/Plugin_Module.C deleted file mode 100644 index f281c39..0000000 --- a/mixer/src/Plugin_Module.C +++ /dev/null @@ -1,880 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Filter module. Can host LADPSA Plugins, or can be inherited from to make internal - modules with special features and appearance. */ - -#include "const.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "Plugin_Module.H" - -#include "debug.h" - -#define HAVE_LIBLRDF 1 -#include "LADSPAInfo.h" - -#include "Chain.H" -//#include "Client/Client.H" - -#include - -#include - - - -static LADSPAInfo *ladspainfo; -Thread* Plugin_Module::plugin_discover_thread; - -/* keep this out of the header to avoid spreading ladspa.h dependency */ -struct Plugin_Module::ImplementationData -{ - const LADSPA_Descriptor *descriptor; -// std::vector m_LADSPABufVec; - std::vector handle; -}; - - - -Plugin_Module::Plugin_Module ( ) : Module( 50, 35, name() ) -{ - init(); - - end(); - - log_create(); -} - -Plugin_Module::~Plugin_Module ( ) -{ - log_destroy(); - plugin_instances( 0 ); -} - - - -void -Plugin_Module::get ( Log_Entry &e ) const -{ -// char s[512]; -// snprintf( s, sizeof( s ), "ladspa:%lu", _idata->descriptor->UniqueID ); - e.add( ":plugin_id", _idata->descriptor->UniqueID ); - - /* these help us display the module on systems which are missing this plugin */ - e.add( ":plugin_ins", _plugin_ins ); - e.add( ":plugin_outs", _plugin_outs ); - - Module::get( e ); -} - -void -Plugin_Module::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":plugin_id" ) ) - { - load( (unsigned long) atoll ( v ) ); - } - else if ( ! strcmp( s, ":plugin_ins" ) ) - { - _plugin_ins = atoi( v ); - } - else if ( ! strcmp( s, ":plugin_outs" ) ) - { - _plugin_outs = atoi( v ); - } - } - - Module::set( e ); -} - - - -void -Plugin_Module::init ( void ) -{ - _latency = 0; - _last_latency = 0; - _idata = new Plugin_Module::ImplementationData(); - _idata->handle.clear(); - /* module will be bypassed until plugin is loaded */ - _bypass = true; - _crosswire = false; - - align( (Fl_Align)FL_ALIGN_CENTER | FL_ALIGN_INSIDE ); -// color( (Fl_Color)fl_color_average( FL_MAGENTA, FL_WHITE, 0.5f ) ); - - int tw, th, tx, ty; - - bbox( tx, ty, tw, th ); -} - -void -Plugin_Module::update ( void ) -{ - if ( _last_latency != _latency ) - { - DMESSAGE( "Plugin latency changed to %lu", (unsigned long)_latency ); - - chain()->client()->recompute_latencies(); - } - - _last_latency = _latency; - - update_tooltip(); -} - -int -Plugin_Module::can_support_inputs ( int n ) -{ - /* this is the simple case */ - if ( plugin_ins() == n ) - return plugin_outs(); - /* e.g. MONO going into STEREO */ - /* we'll duplicate our inputs */ - else if ( n < plugin_ins() && - 1 == n ) - { - return plugin_outs(); - } - /* e.g. STEREO going into MONO */ - /* we'll run multiple instances of the plugin */ - else if ( n > plugin_ins() && - ( plugin_ins() == 1 && plugin_outs() == 1 ) ) - { - return n; - } - - return -1; -} - -bool -Plugin_Module::configure_inputs( int n ) -{ - unsigned int inst = _idata->handle.size(); - - if ( ninputs() != n ) - { - _crosswire = false; - - if ( n != ninputs() ) - { - if ( 1 == n && plugin_ins() > 1 ) - { - DMESSAGE( "Cross-wiring plugin inputs" ); - _crosswire = true; - - audio_input.clear(); - - for ( int i = n; i--; ) - audio_input.push_back( Port( this, Port::INPUT, Port::AUDIO ) ); - } - else if ( n >= plugin_ins() && - ( plugin_ins() == 1 && plugin_outs() == 1 ) ) - { - DMESSAGE( "Running multiple instances of plugin" ); - - audio_input.clear(); - audio_output.clear(); - - for ( int i = n; i--; ) - { - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - } - - inst = n; - } - else if ( n == plugin_ins() ) - { - DMESSAGE( "Plugin input configuration is a perfect match" ); - } - else - { - DMESSAGE( "Unsupported input configuration" ); - return false; - } - } - } - - if ( loaded() ) - { - bool b = bypass(); - if ( inst != _idata->handle.size() ) - { - if ( !b ) - deactivate(); - - if ( plugin_instances( inst ) ) - instances( inst ); - else - return false; - - if ( !b ) - activate(); - } - } - - return true; -} - -void * -Plugin_Module::discover_thread ( void * ) -{ - THREAD_ASSERT( Plugin_Discover ); - - DMESSAGE( "Discovering plugins in the background" ); - - ladspainfo = new LADSPAInfo(); - - return NULL; -} - -/* Spawn a background thread for plugin discovery */ -void -Plugin_Module::spawn_discover_thread ( void ) -{ - if ( plugin_discover_thread ) - { - FATAL( "Plugin discovery thread is already running or has completed" ); - } - - plugin_discover_thread = new Thread( "Plugin_Discover" ); - - plugin_discover_thread->clone( &Plugin_Module::discover_thread, NULL ); -} - -void -Plugin_Module::join_discover_thread ( void ) -{ - plugin_discover_thread->join(); -} - -/* return a list of available plugins */ -std::list -Plugin_Module::get_all_plugins ( void ) -{ - if ( !ladspainfo ) - { - if ( ! plugin_discover_thread ) - ladspainfo = new LADSPAInfo(); - else - plugin_discover_thread->join(); - } - - std::vector plugins = ladspainfo->GetPluginInfo(); - - std::list pr; - - int j = 0; - for (std::vector::iterator i=plugins.begin(); - i!=plugins.end(); i++, j++) - { - Plugin_Info pi; - - // pi[j].path = i->Name.c_str(); - pi.path = NULL; - pi.id = i->UniqueID; - pi.author = i->Maker; - pi.name = i->Name; - pi.audio_inputs = i->AudioInputs; - pi.audio_outputs = i->AudioOutputs; - pi.category = "Unclassified"; - pr.push_back( pi ); - } - - pr.sort(); - - const std::vector pe = ladspainfo->GetMenuList(); - - for (std::vector::const_iterator i= pe.begin(); - i !=pe.end(); i++ ) - { - for ( std::list::iterator j = pr.begin(); j != pr.end(); j++ ) - { - if ( j->id == i->UniqueID ) - { - j->category = i->Category; - } - } - } - - return pr; -} - -bool -Plugin_Module::plugin_instances ( unsigned int n ) -{ - if ( _idata->handle.size() > n ) - { - for ( int i = _idata->handle.size() - n; i--; ) - { - DMESSAGE( "Destroying plugin instance" ); - - LADSPA_Handle h = _idata->handle.back(); - - if ( _idata->descriptor->deactivate ) - _idata->descriptor->deactivate( h ); - if ( _idata->descriptor->cleanup ) - _idata->descriptor->cleanup( h ); - - _idata->handle.pop_back(); - } - } - else if ( _idata->handle.size() < n ) - { - for ( int i = n - _idata->handle.size(); i--; ) - { - LADSPA_Handle h; - - DMESSAGE( "Instantiating plugin... with sample rate %lu", (unsigned long)sample_rate()); - - if ( ! (h = _idata->descriptor->instantiate( _idata->descriptor, sample_rate() ) ) ) - { - WARNING( "Failed to instantiate plugin" ); - return false; - } - - DMESSAGE( "Instantiated: %p", h ); - - _idata->handle.push_back( h ); - - DMESSAGE( "Connecting control ports..." ); - - int ij = 0; - int oj = 0; - for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) - { - if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[k] ) ) - { - if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_input[ij++].buffer() ); - else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_output[oj++].buffer() ); - } - } - - // connect ports to magic bogus value to aid debugging. - for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) - if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, (LADSPA_Data*)0x42 ); - - } - } - - return true; -} - -void -Plugin_Module::bypass ( bool v ) -{ - if ( v != bypass() ) - { - if ( v ) - deactivate(); - else - activate(); - } -} - -nframes_t -Plugin_Module::get_module_latency ( void ) const -{ - for ( unsigned int i = ncontrol_outputs(); i--; ) - { - if ( !strcasecmp( "latency", control_output[i].name() ) ) - { - return control_output[i].control_value(); - } - } - - return 0; -} - -bool -Plugin_Module::load ( unsigned long id ) -{ - if ( !ladspainfo ) - { - if ( ! plugin_discover_thread ) - ladspainfo = new LADSPAInfo(); - else - plugin_discover_thread->join(); - } - - _idata->descriptor = ladspainfo->GetDescriptorByID( id ); - - _plugin_ins = _plugin_outs = 0; - - if ( ! _idata->descriptor ) - { - /* unknown plugin ID */ - WARNING( "Unknown plugin ID: %lu", id ); - label( "----" ); - return false; - } - - label( _idata->descriptor->Name ); - - if ( _idata->descriptor ) - { - if ( LADSPA_IS_INPLACE_BROKEN( _idata->descriptor->Properties ) ) - { - WARNING( "Cannot use this plugin because it is incapable of processing audio in-place" ); - return false; - } - - /* else if ( ! LADSPA_IS_HARD_RT_CAPABLE( _idata->descriptor->Properties ) ) */ - /* { */ - /* WARNING( "Cannot use this plugin because it is incapable of hard real-time operation" ); */ - /* return false; */ - /* } */ - - MESSAGE( "Name: %s", _idata->descriptor->Name ); - - for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i ) - { - if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) ) - { - if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) ) - { - add_port( Port( this, Port::INPUT, Port::AUDIO, _idata->descriptor->PortNames[ i ] ) ); - _plugin_ins++; - } - else if (LADSPA_IS_PORT_OUTPUT(_idata->descriptor->PortDescriptors[i])) - { - _plugin_outs++; - add_port( Port( this, Port::OUTPUT, Port::AUDIO, _idata->descriptor->PortNames[ i ] ) ); - } - } - } - - MESSAGE( "Plugin has %i inputs and %i outputs", _plugin_ins, _plugin_outs); - - for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i ) - { - if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[i] ) ) - { - Port::Direction d = Port::INPUT; - - if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) ) - { - d = Port::INPUT; - } - else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[i] ) ) - { - d = Port::OUTPUT; - } - - Port p( this, d, Port::CONTROL, _idata->descriptor->PortNames[ i ] ); - - p.hints.default_value = 0; - - LADSPA_PortRangeHintDescriptor hd = _idata->descriptor->PortRangeHints[i].HintDescriptor; - - if ( LADSPA_IS_HINT_BOUNDED_BELOW(hd) ) - { - p.hints.ranged = true; - p.hints.minimum = _idata->descriptor->PortRangeHints[i].LowerBound; - if ( LADSPA_IS_HINT_SAMPLE_RATE(hd) ) - { - p.hints.minimum *= sample_rate(); - } - } - if ( LADSPA_IS_HINT_BOUNDED_ABOVE(hd) ) - { - p.hints.ranged = true; - p.hints.maximum = _idata->descriptor->PortRangeHints[i].UpperBound; - if ( LADSPA_IS_HINT_SAMPLE_RATE(hd) ) - { - p.hints.maximum *= sample_rate(); - } - } - - if ( LADSPA_IS_HINT_HAS_DEFAULT(hd) ) - { - - float Max=1.0f, Min=-1.0f, Default=0.0f; - int Port=i; - - // Get the bounding hints for the port - LADSPA_PortRangeHintDescriptor HintDesc=_idata->descriptor->PortRangeHints[Port].HintDescriptor; - if (LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc)) - { - Min=_idata->descriptor->PortRangeHints[Port].LowerBound; - if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc)) - { - Min*=sample_rate(); - } - } - if (LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc)) - { - Max=_idata->descriptor->PortRangeHints[Port].UpperBound; - if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc)) - { - Max*=sample_rate(); - } - } - -#ifdef LADSPA_VERSION -// We've got a version of the header that supports port defaults - if (LADSPA_IS_HINT_HAS_DEFAULT(HintDesc)) { - // LADSPA_HINT_DEFAULT_0 is assumed anyway, so we don't check for it - if (LADSPA_IS_HINT_DEFAULT_1(HintDesc)) { - Default = 1.0f; - } else if (LADSPA_IS_HINT_DEFAULT_100(HintDesc)) { - Default = 100.0f; - } else if (LADSPA_IS_HINT_DEFAULT_440(HintDesc)) { - Default = 440.0f; - } else { - // These hints may be affected by SAMPLERATE, LOGARITHMIC and INTEGER - if (LADSPA_IS_HINT_DEFAULT_MINIMUM(HintDesc) && - LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc)) { - Default=_idata->descriptor->PortRangeHints[Port].LowerBound; - } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(HintDesc) && - LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc)) { - Default=_idata->descriptor->PortRangeHints[Port].UpperBound; - } else if (LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc) && - LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc)) { - // These hints require both upper and lower bounds - float lp = 0.0f, up = 0.0f; - float min = _idata->descriptor->PortRangeHints[Port].LowerBound; - float max = _idata->descriptor->PortRangeHints[Port].UpperBound; - if (LADSPA_IS_HINT_DEFAULT_LOW(HintDesc)) { - lp = 0.75f; - up = 0.25f; - } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(HintDesc)) { - lp = 0.5f; - up = 0.5f; - } else if (LADSPA_IS_HINT_DEFAULT_HIGH(HintDesc)) { - lp = 0.25f; - up = 0.75f; - } - - if (LADSPA_IS_HINT_LOGARITHMIC(HintDesc)) { - - p.hints.type = Port::Hints::LOGARITHMIC; - - if (min==0.0f || max==0.0f) { - // Zero at either end means zero no matter - // where hint is at, since: - // log(n->0) -> Infinity - Default = 0.0f; - } else { - // Catch negatives - bool neg_min = min < 0.0f ? true : false; - bool neg_max = max < 0.0f ? true : false; - - if (!neg_min && !neg_max) { - Default = exp(::log(min) * lp + ::log(max) * up); - } else if (neg_min && neg_max) { - Default = -exp(::log(-min) * lp + ::log(-max) * up); - } else { - // Logarithmic range has asymptote - // so just use linear scale - Default = min * lp + max * up; - } - } - } else { - Default = min * lp + max * up; - } - } - if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc)) { - Default *= sample_rate(); - } - } - - if (LADSPA_IS_HINT_INTEGER(HintDesc)) { - if ( p.hints.ranged && - 0 == (int)p.hints.minimum && - 1 == (int)p.hints.maximum ) - p.hints.type = Port::Hints::BOOLEAN; - else - p.hints.type = Port::Hints::INTEGER; - Default = floorf(Default); - } - if (LADSPA_IS_HINT_TOGGLED(HintDesc)){ - p.hints.type = Port::Hints::BOOLEAN; - } - } -#else - Default = 0.0f; -#endif - p.hints.default_value = Default; - } - - float *control_value = new float; - - *control_value = p.hints.default_value; - - p.connect_to( control_value ); - - add_port( p ); - - DMESSAGE( "Plugin has control port \"%s\" (default: %f)", _idata->descriptor->PortNames[ i ], p.hints.default_value ); - } - } - } - else - { - WARNING( "Failed to load plugin" ); - return false; - } - - int instances = plugin_instances( 1 ); - - if ( instances ) - { - bypass( false ); - } - - return instances; -} - -void -Plugin_Module::set_input_buffer ( int n, void *buf ) -{ - LADSPA_Handle h; - - if ( instances() > 1 ) - { - h = _idata->handle[n]; - n = 0; - } - else - h = _idata->handle[0]; - - for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i ) - if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) && - LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) ) - if ( n-- == 0 ) - _idata->descriptor->connect_port( h, i, (LADSPA_Data*)buf ); -} - -bool -Plugin_Module::loaded ( void ) const -{ - return _idata->descriptor; -} - -void -Plugin_Module::set_output_buffer ( int n, void *buf ) -{ - LADSPA_Handle h; - - if ( instances() > 1 ) - { - h = _idata->handle[n]; - n = 0; - } - else - h = _idata->handle[0]; - - for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i ) - if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[i] ) && - LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) ) - if ( n-- == 0 ) - _idata->descriptor->connect_port( h, i, (LADSPA_Data*)buf ); -} - -void -Plugin_Module::activate ( void ) -{ - if ( !loaded() ) - return; - - DMESSAGE( "Activating plugin \"%s\"", label() ); - - if ( !bypass() ) - FATAL( "Attempt to activate already active plugin" ); - - if ( chain() ) - chain()->client()->lock(); - - if ( _idata->descriptor->activate ) - for ( unsigned int i = 0; i < _idata->handle.size(); ++i ) - _idata->descriptor->activate( _idata->handle[i] ); - - _bypass = false; - - if ( chain() ) - chain()->client()->unlock(); -} - -void -Plugin_Module::deactivate( void ) -{ - if ( !loaded() ) - return; - - DMESSAGE( "Deactivating plugin \"%s\"", label() ); - - if ( chain() ) - chain()->client()->lock(); - - _bypass = true; - - if ( _idata->descriptor->deactivate ) - for ( unsigned int i = 0; i < _idata->handle.size(); ++i ) - _idata->descriptor->deactivate( _idata->handle[i] ); - - if ( chain() ) - chain()->client()->unlock(); -} - -void -Plugin_Module::handle_port_connection_change ( void ) -{ -// DMESSAGE( "Connecting audio ports" ); - - if ( loaded() ) - { - if ( _crosswire ) - { - for ( int i = 0; i < plugin_ins(); ++i ) - set_input_buffer( i, audio_input[0].buffer() ); - } - else - { - for ( unsigned int i = 0; i < audio_input.size(); ++i ) - set_input_buffer( i, audio_input[i].buffer() ); - } - - for ( unsigned int i = 0; i < audio_output.size(); ++i ) - set_output_buffer( i, audio_output[i].buffer() ); - } -} - - - -bool -Plugin_Module::get_impulse_response ( sample_t *buf, nframes_t nframes ) -{ - apply( buf, nframes ); - - if ( buffer_is_digital_black( buf + 1, nframes - 1 )) - /* no impulse response... */ - return false; - - return true; -} - -/** Instantiate a temporary version of the plugin, and run it (in place) against the provided buffer */ -bool -Plugin_Module::apply ( sample_t *buf, nframes_t nframes ) -{ -// actually osc or UI THREAD_ASSERT( UI ); - - LADSPA_Handle h; - - if ( ! (h = _idata->descriptor->instantiate( _idata->descriptor, sample_rate() ) ) ) - { - WARNING( "Failed to instantiate plugin" ); - return false; - } - - int ij = 0; - int oj = 0; - for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) - { - if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[k] ) ) - { - if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_input[ij++].buffer() ); - else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_output[oj++].buffer() ); - } - } - - - if ( _idata->descriptor->activate ) - _idata->descriptor->activate( h ); - - int tframes = 512; - float tmp[tframes]; - - memset( tmp, 0, sizeof( float ) * tframes ); - - for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) - if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, tmp ); - - - /* flush any parameter interpolation */ - _idata->descriptor->run( h, tframes ); - - for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) - if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) ) - _idata->descriptor->connect_port( h, k, buf ); - - /* run for real */ - _idata->descriptor->run( h, nframes ); - - if ( _idata->descriptor->deactivate ) - _idata->descriptor->deactivate( h ); - if ( _idata->descriptor->cleanup ) - _idata->descriptor->cleanup( h ); - - return true; -} -/**********/ -/* Client */ -/**********/ - -void -Plugin_Module::process ( nframes_t nframes ) -{ - handle_port_connection_change(); - - if ( unlikely( bypass() ) ) - { - /* If this is a mono to stereo plugin, then duplicate the input channel... */ - /* There's not much we can do to automatically support other configurations. */ - if ( ninputs() == 1 && noutputs() == 2 ) - { - buffer_copy( (sample_t*)audio_output[1].buffer(), (sample_t*)audio_input[0].buffer(), nframes ); - } - - _latency = 0; - } - else - { - for ( unsigned int i = 0; i < _idata->handle.size(); ++i ) - _idata->descriptor->run( _idata->handle[i], nframes ); - - _latency = get_module_latency(); - } -} - - diff --git a/mixer/src/Plugin_Module.H b/mixer/src/Plugin_Module.H deleted file mode 100644 index 7409e8d..0000000 --- a/mixer/src/Plugin_Module.H +++ /dev/null @@ -1,154 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Module.H" -#include "Loggable.H" - -class Fl_Menu_Button; -class Thread; - -class Plugin_Module : public Module { - - static Thread *plugin_discover_thread; - -public: - - class Plugin_Info - { - public: - const char *path; - unsigned long id; - std::string name; - std::string author; - std::string category; - int audio_inputs; - int audio_outputs; - const char *type; - bool favorite; - - Plugin_Info ( ) - { - path = 0; - id = 0; - - audio_inputs = 0; - audio_outputs = 0; - type = "LADSPA"; - favorite = 0; - } - - - bool operator< ( const Plugin_Info &rhs ) { - return strcmp( name.c_str(), rhs.name.c_str() ) < 1; - } - }; - - bool load ( unsigned long id ); - -private: - - volatile nframes_t _latency; - nframes_t _last_latency; - - void init ( void ); - - void bbox ( int &X, int &Y, int &W, int &H ) - { - X = x(); - Y = y() + 5; - W = w(); - H = h() - 10; - } - - void cb_handle(Fl_Widget*); - static void cb_handle(Fl_Widget*, void*); - - Fl_Button *close_button; - - struct ImplementationData; - - ImplementationData *_idata; - - int _plugin_ins; - int _plugin_outs; - bool _crosswire; - - static void *discover_thread ( void * ); - - - void set_input_buffer ( int n, void *buf ); - void set_output_buffer ( int n, void *buf ); - void set_control_buffer ( int n, void *buf ); - void activate ( void ); - void deactivate ( void ); - - bool apply ( sample_t *buf, nframes_t nframes ); - void process ( unsigned long nframes ); - - bool plugin_instances ( unsigned int ); - - void connect_ports ( void ); - - bool loaded ( void ) const; - -public: - - virtual bool get_impulse_response ( sample_t *buf, nframes_t nframes ); - - virtual nframes_t get_module_latency ( void ) const; - - virtual void update ( void ); - - static std::list get_all_plugins ( void ); - - static void spawn_discover_thread ( void ); - static void join_discover_thread ( void ); - - Plugin_Module ( ); - virtual ~Plugin_Module(); - - int plugin_ins ( void ) const { return _plugin_ins; } - int plugin_outs ( void ) const { return _plugin_outs; } - - void select_plugin ( unsigned long id ); - - const char *name ( void ) const { return "Plugin"; } - - int can_support_inputs ( int ); - bool configure_inputs ( int ); - - virtual bool bypass ( void ) const { return _bypass; } - virtual void bypass ( bool v ); - - virtual void process ( nframes_t ); - - void handle_port_connection_change ( void ); - - LOG_CREATE_FUNC( Plugin_Module ); - - MODULE_CLONE_FUNC( Plugin_Module ); - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - -}; diff --git a/mixer/src/Project.C b/mixer/src/Project.C deleted file mode 100644 index 777704c..0000000 --- a/mixer/src/Project.C +++ /dev/null @@ -1,350 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Routings for opening/closing/creation of projects. All the actual - project state belongs to Timeline and other classes. */ - -/* Project management routines. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Loggable.H" -#include "Project.H" - -#include - -#include "const.h" -#include "debug.h" -#include "file.h" - -#include "Mixer.H" - -const int PROJECT_VERSION = 1; - - - -const char *Project::_errstr[] = -{ - "Not a Non-Mixer project", - "Locked by another process", - "Access denied", - "Incompatible project version" -}; - -char Project::_name[256]; -char Project::_created_on[40]; -char Project::_path[512]; -bool Project::_is_open = false; -bool Project::_is_opening = false; -int Project::_lockfd = 0; - - - -/***********/ -/* Private */ -/***********/ - -void -Project::set_name ( const char *name ) -{ - strcpy( Project::_name, name ); - - if ( Project::_name[ strlen( Project::_name ) - 1 ] == '/' ) - Project::_name[ strlen( Project::_name ) - 1 ] = '\0'; - - char *s = rindex( Project::_name, '/' ); - - s = s ? s + 1 : Project::_name; - - memmove( Project::_name, s, strlen( s ) + 1 ); - - for ( s = Project::_name; *s; ++s ) - if ( *s == '_' || *s == '-' ) - *s = ' '; -} - -void -Project::name ( const char *name ) -{ - strcpy( Project::_name, name ); -} - -bool -Project::write_info ( void ) -{ - FILE *fp; - - if ( ! ( fp = fopen( "info", "w" ) ) ) - { - WARNING( "could not open project info file for writing." ); - return false; - } - - char s[40]; - - if ( ! *_created_on ) - { - time_t t = time( NULL ); - ctime_r( &t, s ); - s[ strlen( s ) - 1 ] = '\0'; - } - else - strcpy( s, _created_on ); - - fprintf( fp, "created by\n\t%s\ncreated on\n\t%s\nversion\n\t%d\n", - APP_TITLE " " VERSION, - s, - PROJECT_VERSION ); - - fclose( fp ); - - return true; -} - -bool -Project::read_info ( int *version, char **creation_date, char **created_by ) -{ - FILE *fp; - - if ( ! ( fp = fopen( "info", "r" ) ) ) - { - WARNING( "could not open project info file for reading." ); - return false; - } - - *version = 0; - *creation_date = 0; - *created_by = 0; - - char *name, *value; - - while ( fscanf( fp, "%m[^\n]\n\t%m[^\n]\n", &name, &value ) == 2 ) - { - MESSAGE( "Info: %s = %s", name, value ); - - if ( ! strcmp( name, "version" ) ) - *version = atoi( value ); - else if ( ! strcmp( name, "created on" ) ) - *creation_date = strdup( value ); - else if ( ! strcmp( name, "created by" ) ) - *created_by = strdup( value ); - - free( name ); - free( value ); - } - - fclose( fp ); - - return true; -} - -/**********/ -/* Public */ -/**********/ - -/** Save out any settings and unjournaled state... */ -bool -Project::save ( void ) -{ - if ( ! open() ) - return true; - -// tle->save_timeline_settings(); - - int r = mixer->save(); - -// Loggable::clear_dirty(); - - return r; -// return Loggable::save_unjournaled_state(); -} - - -/** Close the project (reclaiming all memory) */ -bool -Project::close ( void ) -{ - if ( ! open() ) - return true; - - if ( ! save() ) - return false; - - Loggable::close(); -/* // write_info(); */ - - _is_open = false; - - *Project::_name = '\0'; - *Project::_created_on = '\0'; - - release_lock( &_lockfd, ".lock" ); - - return true; -} - -/** Ensure a project is valid before opening it... */ -bool -Project::validate ( const char *name ) -{ - bool r = true; - - char pwd[512]; - - fl_filename_absolute( pwd, sizeof( pwd ), "." ); - - if ( chdir( name ) ) - { - WARNING( "Cannot change to project dir \"%s\"", name ); - return false; - } - - if ( ! exists( "info" ) || - ! exists( "snapshot" )) - { - WARNING( "Not a Non-Mixer project: \"%s\"", name ); - r = false; - } - - chdir( pwd ); - - return r; -} - -/** Try to open project /name/. Returns 0 if sucsessful, an error code - * otherwise */ -int -Project::open ( const char *name ) -{ - if ( ! validate( name ) ) - return E_INVALID; - - close(); - - chdir( name ); - - if ( ! acquire_lock( &_lockfd, ".lock" ) ) - return E_LOCKED; - - int version; - char *creation_date; - char *created_by; - - if ( ! read_info( &version, &creation_date, &created_by ) ) - return E_INVALID; - - if ( strncmp( created_by, APP_TITLE, strlen( APP_TITLE ) ) ) - return E_INVALID; - - if ( version != PROJECT_VERSION ) - return E_VERSION; - - _is_opening = true; - - if ( ! Loggable::replay( "snapshot" ) ) - return E_INVALID; - - if ( creation_date ) - { - strcpy( _created_on, creation_date ); - free( creation_date ); - } - else - *_created_on = 0; - - - getcwd( _path, sizeof( _path ) ); - - set_name( _path ); - - _is_open = true; - - _is_opening = false; -// tle->load_timeline_settings(); - -// timeline->zoom_fit(); - -// Loggable::clear_dirty(); - - MESSAGE( "Loaded project \"%s\"", name ); - - return 0; -} - -/** Create a new project /name/ from existing template - * /template_name/ */ -bool -Project::create ( const char *name, const char *template_name ) -{ - if ( exists( name ) ) - { - WARNING( "Project already exists" ); - return false; - } - - close(); - - if ( mkdir( name, 0777 ) ) - { - WARNING( "Cannot create project directory: %s", name ); - return false; - } - - if ( chdir( name ) ) - { - FATAL( "WTF? Cannot change to new project directory" ); - return false; - } - -// mkdir( "sources", 0777 ); - creat( "snapshot", 0666 ); - - /* TODO: copy template */ - - write_info(); - - if ( open( name ) == 0 ) - { -// /* add the bare essentials */ -// timeline->beats_per_minute( 0, 120 ); -// timeline->time( 0, 4, 4 ); - - MESSAGE( "Created project \"%s\" from template \"%s\"", name, template_name ); - return true; - } - else - { - WARNING( "Failed to open newly created project" ); - return false; - } -} - -/** Replace the journal with a snapshot of the current state */ -void -Project::compact ( void ) -{ - Loggable::compact(); -} diff --git a/mixer/src/Project.H b/mixer/src/Project.H deleted file mode 100644 index 42328dc..0000000 --- a/mixer/src/Project.H +++ /dev/null @@ -1,66 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008, 2010 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -const char template_dir[] = "share/non-daw/templates"; -const char user_template_dir[] = "~/.non-daw/templates"; - -#include "types.h" - -class Project -{ - - static int _lockfd; - static bool _is_open; - static bool _is_opening; - static char _name[256]; - static char _path[512]; - static char _created_on[40]; - - static bool write_info ( void ); - static bool read_info ( int *version, char **creation_date, char **created_by ); - static void set_name ( const char *name ); - static const char *_errstr[]; - -public: - - enum - { - E_INVALID = -1, - E_LOCKED = -2, - E_PERM = -3, - E_SAMPLERATE = -4, - E_VERSION = -5 - }; - - static const char *errstr ( int n ) { return _errstr[ ( 0 - n ) - 1 ]; } - - static const char *name ( void ) { return Project::_name; } - static void name ( const char *v ); - static void compact ( void ); - static bool close ( void ); - static bool save ( void ); - static bool validate ( const char *name ); - static int open ( const char *name ); - static bool open ( void ) { return _is_open; } - static bool create ( const char *name, const char *template_name ); - - static const char *path ( void ) { return _path; } - static const char *created_on ( void ) { return _created_on; } - static const bool is_opening ( void ) { return _is_opening; } -}; diff --git a/mixer/src/Spatialization_Console.C b/mixer/src/Spatialization_Console.C deleted file mode 100644 index e82527a..0000000 --- a/mixer/src/Spatialization_Console.C +++ /dev/null @@ -1,229 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -#include -#include -#include -#include - -#include - -#include "Module.H" -#include "Spatialization_Console.H" -#include "Controller_Module.H" -#include "Chain.H" -#include "Panner.H" -#include "Mixer_Strip.H" -#include "Mixer.H" - -#include "debug.h" -#include - - - -Spatialization_Console::Spatialization_Console ( void ) : Fl_Double_Window( 850, 850 ) -{ - _resized = false; - - label( "Spatialization Console" ); - - labelfont( FL_HELVETICA ); - labelsize( 14 ); - - int padding = 48; - int S = 802; - - if ( fl_display ) - /* don't open the display in noui mode... */ - { - int sx, sy, sw, sh; - - Fl::screen_xywh( sx, sy, sw, sh ); - - if ( sw < 850 || sh < 850 ) - { - /* if screen isn't big enough, use smaller version of control */ - S = 502; - } - } - - panner = new Panner( 25,25, S, S ); - panner->callback( cb_panner_value_handle, this ); - panner->when( FL_WHEN_CHANGED ); - - size( S + padding, S + padding ); - - callback( cb_window, this ); - end(); - - make_controls(); - - mixer->spatialization_console = this; -} - -Spatialization_Console::~Spatialization_Console ( ) -{ -// controls_by_port.clear(); - mixer->spatialization_console = NULL; - -} - - -void -Spatialization_Console::get ( Log_Entry &e ) const -{ - e.add( ":range", panner->range() ); - e.add( ":projection", panner->projection() ); - e.add( ":shown", ((const Fl_Double_Window*)this)->shown() ); -} - -void -Spatialization_Console::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! ( strcmp( s, ":range" ) ) ) - panner->range( atoi( v ) ); - if ( ! ( strcmp( s, ":projection" ) ) ) - panner->projection( atoi( v ) ); - else if ( ! ( strcmp( s, ":shown" ) ) ) - { - if ( atoi( v ) ) - { - if ( fl_display ) - { - show(); - } - } - else - hide(); - } - } -} - - - -void -Spatialization_Console::cb_window ( Fl_Widget *w, void *v ) -{ - ((Spatialization_Console*)v)->cb_window(w); -} - -void -Spatialization_Console::cb_window ( Fl_Widget *w ) -{ - w->hide(); - mixer->update_menu(); -} - - - -void -Spatialization_Console::make_controls ( void ) -{ - panner->clear_points(); - - for ( int i = 0; i < mixer->nstrips(); i++ ) - { - Mixer_Strip *o = mixer->track_by_number( i ); - - if ( o->spatializer() ) - { - Panner::Point p; - - p.color = o->color(); - p.userdata = o->spatializer(); - p.label = o->name(); - - if ( o->spatializer()->is_controlling() ) - { - p.visible = true; - - p.azimuth( o->spatializer()->control_output[0].control_value() ); - p.elevation( o->spatializer()->control_output[1].control_value() ); - if ( o->spatializer()->control_output[2].connected() ) - { - p.radius_enabled = true; - p.radius( o->spatializer()->control_output[2].control_value() ); - } - } - else - p.visible = false; - - panner->add_point(p); - } - } - - panner->redraw(); -} - -void -Spatialization_Console::cb_panner_value_handle ( Fl_Widget *w, void *v ) -{ -// callback_data *cd = (callback_data*)v; - - Spatialization_Console *sc = (Spatialization_Console*)v; - - Panner::Point *p = sc->panner->pushed(); - - Controller_Module *cm = (Controller_Module*)p->userdata; - - cm->control_output[0].control_value( p->azimuth() ); - cm->control_output[1].control_value( p->elevation() ); - if ( p->radius_enabled ) - cm->control_output[2].control_value( p->radius() ); -} - -/* Display changes initiated via automation or from other parts of the GUI */ -void -Spatialization_Console::handle_control_changed ( Controller_Module *m ) -{ - if ( Fl::pushed() == panner ) - return; - - for ( int i = 0; i < panner->points(); i++ ) - { - Panner::Point *p = panner->point(i); - - if ( p->userdata == m ) - { - p->azimuth( m->control_output[0].control_value() ); - p->elevation( m->control_output[1].control_value() ); - if ( p->radius_enabled ) - p->radius( m->control_output[2].control_value() ); - - if ( panner->visible_r() ) - panner->redraw(); - - break; - } - } -} - -void -Spatialization_Console::update ( void ) -{ - make_controls(); -} diff --git a/mixer/src/Spatialization_Console.H b/mixer/src/Spatialization_Console.H deleted file mode 100644 index 5ca0274..0000000 --- a/mixer/src/Spatialization_Console.H +++ /dev/null @@ -1,66 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2009 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include -#include "Loggable.H" - -class Fl_Pack; -class Fl_Flowpack; -class Module; -class Fl_Menu_Button; -class Panner; -class Controller_Module; -#include - -class Spatialization_Console : public Loggable, public Fl_Double_Window -{ - Panner *panner; - - static void cb_panner_value_handle ( Fl_Widget *w, void *v ); - void make_controls ( void ); - - static void cb_window ( Fl_Widget *w, void *v ); - static void cb_window ( Fl_Widget *w ); - - bool _resized; - - int azimuth_port_number; - int elevation_port_number; - - std::vector controls_by_port; - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - -public: - - LOG_CREATE_FUNC( Spatialization_Console ); - - void handle_control_changed ( Controller_Module *m ); - - void update ( void ); - - Spatialization_Console ( ); - virtual ~Spatialization_Console ( ); -}; diff --git a/mixer/src/Spatializer_Module.C b/mixer/src/Spatializer_Module.C deleted file mode 100644 index 5649053..0000000 --- a/mixer/src/Spatializer_Module.C +++ /dev/null @@ -1,862 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include "Spatializer_Module.H" -#include "dsp.h" -#include "Module_Parameter_Editor.H" - -static const float max_distance = 15.0f; - -#include - -class filter -{ -protected: - - float _sample_rate; - float _w; - float _last_output; - float _last_cutoff; - float _amount_of_current; - float _amount_of_last; - bool _bypass; - - void recalculate ( float cutoff ) - { - _last_cutoff = cutoff; - - if (_last_cutoff <= 10 ) - { - _bypass = true; - } - else if (_last_cutoff > _sample_rate * 0.5f ) - { - _bypass = true; - } - else - { - const float c = 2.0f - cosf(_w * _last_cutoff); - _amount_of_last = c - sqrtf(c * c - 1.0f); - _amount_of_current = 1 - _amount_of_last; - - _bypass = false; - } - } - -public: - - void sample_rate ( nframes_t srate ) - { - _sample_rate = srate; - _w = (2 * M_PI) / (float)srate; - } - - filter () - { - _last_output = 0; - _last_cutoff = 0; - _w = 0; - _sample_rate = 0; - _amount_of_current = 0; - _amount_of_last = 0; - _bypass = false; - } - - - void - run_lowpass ( float *buf, float cutoff, nframes_t nframes ) - { - if (cutoff != _last_cutoff) - { - recalculate( cutoff ); - } - - if ( !_bypass ) - { - while ( nframes-- ) - { - *buf = _last_output = (_amount_of_current * *buf + _amount_of_last * _last_output); - buf++; - } - } - } - - void - run_highpass ( float *buf, float cutoff, nframes_t nframes ) - { - if (cutoff != _last_cutoff) - { - recalculate( cutoff ); - } - - if ( !_bypass ) - { - while ( nframes-- ) - { - _last_output = ((_amount_of_current * *buf) + (_amount_of_last * _last_output)); - *buf = *buf - _last_output; - buf++; - } - } - } - -}; - -class delay -{ - unsigned int _sample_rate; - float *_buffer; - long _write_index; - unsigned int _buffer_mask; - float _max_delay; - nframes_t _samples_since_motion; - nframes_t _interpolation_delay_samples; - float _interpolation_delay_coeff; - -public: - - void sample_rate ( float srate ) - { - if ( _buffer ) - free( _buffer ); - - unsigned int size, minsize; - minsize = (unsigned long)(srate * _max_delay); - - size = 1; - while (size < minsize) - size <<= 1; - - _buffer = (float *)calloc(size, sizeof(float)); - - _buffer_mask = size - 1; - - _sample_rate = srate; - - _write_index = 0; - - _interpolation_delay_samples = 0.2f * srate; - _interpolation_delay_coeff = 1.0f / (float)_interpolation_delay_samples; - } - - - delay ( float max_delay ) - { - _interpolation_delay_samples = 0; - _interpolation_delay_coeff = 0; - _samples_since_motion = 0; - _max_delay = max_delay; - _write_index = 0; - _sample_rate = 0; - _buffer = 0; - _buffer_mask =0; - } - - ~delay ( ) - { - if ( _buffer ) - free( _buffer ); - } - - void run ( float *buf, float *delaybuf, float delay, nframes_t nframes ) - { - const nframes_t min_delay_samples = 4; - - - if ( delaybuf ) - { - for (nframes_t i = 0; i < nframes; i++ ) - { - float delay_samples = delaybuf[i] * _sample_rate; - - if ( delay_samples > _buffer_mask + 1 ) - delay_samples = _buffer_mask; - else if ( delay_samples < min_delay_samples ) - delay_samples = min_delay_samples; - - long idelay_samples = (long)delay_samples; - const float frac = delay_samples - idelay_samples; - const long read_index = _write_index - idelay_samples; - - _buffer[_write_index++ & _buffer_mask] = buf[i]; - - const float read = interpolate_cubic (frac, - _buffer[(read_index-1) & _buffer_mask], - _buffer[read_index & _buffer_mask], - _buffer[(read_index+1) & _buffer_mask], - _buffer[(read_index+2) & _buffer_mask]); - - buf[i] = read; - } - - _samples_since_motion = 0; - } - else - { - float delay_samples = delay * _sample_rate; - - if ( delay_samples > _buffer_mask + 1 ) - delay_samples = _buffer_mask; - else if ( delay_samples < min_delay_samples ) - delay_samples = min_delay_samples; - - long idelay_samples = (long)delay_samples; - - if ( _samples_since_motion >= _interpolation_delay_samples ) - { - /* switch to non-interpolating mode */ - for (nframes_t i = 0; i < nframes; i++ ) - { - const long read_index = _write_index - idelay_samples; - - _buffer[_write_index++ & _buffer_mask] = buf[i]; - - const float read = _buffer[read_index & _buffer_mask]; - - buf[i] = read; - } - } - else - { - /* linearly interpolate our way to an integer sample delay */ - - float frac = delay_samples - idelay_samples; - - const float scale = 1.0f - (_samples_since_motion * _interpolation_delay_coeff); - - for (nframes_t i = 0; i < nframes; i++ ) - { - const long read_index = _write_index - idelay_samples; - - _buffer[_write_index++ & _buffer_mask] = buf[i]; - - frac *= scale; - - const float read = interpolate_cubic (frac, - _buffer[(read_index-1) & _buffer_mask], - _buffer[read_index & _buffer_mask], - _buffer[(read_index+1) & _buffer_mask], - _buffer[(read_index+2) & _buffer_mask]); - - buf[i] = read; - } - - _samples_since_motion += nframes; - } - } - } -}; - -class ambisonic_panner -{ - /* last values */ - float _x, _y, _z; - - /* for stereo */ - float _xr, _yr; - - static inline void spherical_to_cartesian (float a, float e, float &x, float &y, float &z ) - { - a *= DEG2RAD; - e *= DEG2RAD; - - z = sinf(e); - const float ce = cosf(e); - x = ce * cosf(-a); - y = ce * sinf(-a); - } - -public: - - ambisonic_panner ( ) - { - _x = _y = _z = _xr = _yr = 1.0f; - } - - void - run_mono ( float *in, - float *out_w, float *out_x, float *out_y, float *out_z, - float a, float e, - nframes_t nframes ) - { - float x = _x; - float y = _y; - float z = _z; - - spherical_to_cartesian( a, e, _x, _y, _z ); - - const float c = 1.0f / (float)nframes; - - /* calculate increment for linear interpolation */ - const float dx = (_x - x) * c; - const float dy = (_y - y) * c; - const float dz = (_z - z) * c; - - while ( nframes-- ) - { - x += dx; - y += dy; - z += dz; - - const float t = *in++; - - *out_w++ = ONEOVERSQRT2 * t; - *out_x++ = x * t; - *out_y++ = y * t; - *out_z++ = z * t; - } - } - - void - run_stereo ( float *in_l, float *in_r, - float *out_w, float *out_x, float *out_y, float *out_z, - float a, float e, float w, - nframes_t nframes ) - { - float x = _x; - float y = _y; - float z = _z; - float xr = _xr; - float yr = _yr; - - w *= 0.5f; - - spherical_to_cartesian( a - w, e, _x, _y, _z ); - spherical_to_cartesian( a + w, e, _xr, _yr, _z ); - - const float c = 1.0f / (float)nframes; - - /* calculate increment for linear interpolation */ - const float dx = (_x - x) * c; - const float dy = (_y - y) * c; - const float dz = (_z - z) * c; - const float dxr = (_xr - xr) * c; - const float dyr = (_yr - yr) * c; - - while ( nframes-- ) - { - x += dx; - y += dy; - z += dz; - xr += dxr; - yr += dyr; - - const float L = *in_l++; - const float R = *in_r++; - - const float LR = L + R; - - *out_w++ = ONEOVERSQRT2 * LR; - *out_x++ = x * L + xr * R; - *out_y++ = y * L + yr * R; - *out_z++ = z * LR; - } - } -}; - - - -Spatializer_Module::Spatializer_Module ( ) : JACK_Module ( false ) -{ - is_default( false ); - - _panner = 0; - _early_panner = 0; - - { - Port p( this, Port::INPUT, Port::CONTROL, "Azimuth" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -180.0f; - p.hints.maximum = 180.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Elevation" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -90.0f; - p.hints.maximum = 90.0f; - p.hints.default_value = 0.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Radius" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = 0.0f; - p.hints.maximum = max_distance; - p.hints.default_value = 1.0f; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Highpass (Hz)" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = 0.0f; - p.hints.maximum = 600.0f; - p.hints.default_value = 0.0f; - p.hints.visible = false; - - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Width" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -90.0f; - p.hints.maximum = 90.0f; - p.hints.default_value = 90.0f; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Angle" ); - p.hints.type = Port::Hints::LINEAR; - p.hints.ranged = true; - p.hints.minimum = -180.0f; - p.hints.maximum = +180.0f; - p.hints.default_value = 0.0f; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Advanced Options" ); - p.hints.type = Port::Hints::BOOLEAN; - p.hints.ranged = true; - p.hints.minimum = 0.0f; - p.hints.maximum = 1.0f; - p.hints.default_value = 0.0f; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Speed of Sound" ); - p.hints.type = Port::Hints::BOOLEAN; - p.hints.ranged = true; - p.hints.minimum = 0.0f; - p.hints.maximum = 1.0f; - p.hints.default_value = 1.0f; - p.hints.visible = false; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Late Gain (dB)" ); - p.hints.type = Port::Hints::LOGARITHMIC; - p.hints.ranged = true; - p.hints.minimum = -70.0f; - p.hints.maximum = 6.0f; - p.hints.default_value = 0.0f; - p.hints.visible = false; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - { - Port p( this, Port::INPUT, Port::CONTROL, "Early Gain (dB)" ); - p.hints.type = Port::Hints::LOGARITHMIC; - p.hints.ranged = true; - p.hints.minimum = -70.0f; - p.hints.maximum = 6.0f; - p.hints.default_value = 0.0f; - p.hints.visible = false; - p.connect_to( new float ); - p.control_value( p.hints.default_value ); - - add_port( p ); - } - - log_create(); - - _panner = new ambisonic_panner(); - _early_panner = new ambisonic_panner(); - - labelsize(9); - - color( FL_DARK1 ); - - copy_label( "Spatializer" ); - align(FL_ALIGN_LEFT|FL_ALIGN_TOP|FL_ALIGN_INSIDE); - - gain_smoothing.sample_rate( sample_rate() ); - late_gain_smoothing.sample_rate( sample_rate() ); - early_gain_smoothing.sample_rate( sample_rate() ); - delay_smoothing.cutoff( 0.5f ); - delay_smoothing.sample_rate( sample_rate() ); -} - -Spatializer_Module::~Spatializer_Module ( ) -{ - configure_inputs(0); - delete _early_panner; - delete _panner; - for ( unsigned int i = 0; i < control_input.size(); i++ ) - delete (float*)control_input[i].buffer(); -} - - - - -void -Spatializer_Module::handle_sample_rate_change ( nframes_t n ) -{ - gain_smoothing.sample_rate( n ); - delay_smoothing.sample_rate( n ); - early_gain_smoothing.sample_rate( n ); - late_gain_smoothing.sample_rate( n ); - - for ( unsigned int i = 0; i < audio_input.size(); i++ ) - { - _lowpass[i]->sample_rate( n ); - _highpass[i]->sample_rate( n ); - _delay[i]->sample_rate( n ); - } -} - -void -Spatializer_Module::draw ( void ) -{ - int W = 5; - - child(0)->size( w() - W, h() ); - Module::draw_box(x(),y(),w() - W,h()); - Module::draw_label(x() + 4,y(),w() - W,h()); - - Module *m = this; - - fl_color( fl_darker( FL_FOREGROUND_COLOR ) ); - - int spacing, offset; - - int ni = aux_audio_output.size(); - - spacing = h() / ni; - offset = spacing / 2; - for ( int i = ni; i--; ) - { - int xi = offset + ( spacing * i ); - fl_rectf( m->x() + m->w() - W, m->y() + xi, W, 2 ); - } -} - -void -Spatializer_Module::process ( nframes_t nframes ) -{ - float azimuth = control_input[0].control_value(); - float elevation = control_input[1].control_value(); - float radius = control_input[2].control_value(); - float highpass_freq = control_input[3].control_value(); - float width = control_input[4].control_value(); - float angle = control_input[5].control_value(); -// bool more_options = control_input[6].control_value(); - bool speed_of_sound = control_input[7].control_value() > 0.5f; - float late_gain = DB_CO( control_input[8].control_value() ); - float early_gain = DB_CO( control_input[9].control_value() ); - - control_input[3].hints.visible = highpass_freq != 0.0f; - - float delay_seconds = 0.0f; - - if ( speed_of_sound && radius > 1.0f ) - delay_seconds = ( radius - 1.0f ) / 340.29f; - - /* direct sound follows inverse square law */ - /* but it's just the inverse as far as SPL goes */ - - /* let's not go nuts... */ - if ( radius < 0.01f ) - radius = 0.01f; - - float gain = 1.0f / radius; - - /* float cutoff_frequency = gain * LOWPASS_FREQ; */ - - sample_t gainbuf[nframes]; - sample_t delaybuf[nframes]; - - bool use_gainbuf = false; - bool use_delaybuf = delay_smoothing.apply( delaybuf, nframes, delay_seconds ); - - for ( unsigned int i = 0; i < audio_input.size(); i++ ) - { - sample_t *buf = (sample_t*) audio_input[i].buffer(); - - /* frequency effects */ - _highpass[i]->run_highpass( buf, highpass_freq, nframes ); - - /* send to late reverb */ - if ( i == 0 ) - buffer_copy( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), buf, nframes ); - else - buffer_mix( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), buf, nframes ); - - } - - { - use_gainbuf = late_gain_smoothing.apply( gainbuf, nframes, late_gain ); - - /* gain effects */ - if ( unlikely( use_gainbuf ) ) - buffer_apply_gain_buffer( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), gainbuf, nframes ); - else - buffer_apply_gain( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), nframes, late_gain ); - } - - float early_angle = azimuth - angle; - if ( early_angle > 180.0f ) - early_angle = -180 - ( early_angle - 180 ); - else if ( early_angle < -180.0f ) - early_angle = 180 - ( early_angle + 180 ); - - /* send to early reverb */ - if ( audio_input.size() == 1 ) - { - _early_panner->run_mono( (sample_t*)audio_input[0].buffer(), - (sample_t*)aux_audio_output[1].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[2].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[3].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[4].jack_port()->buffer(nframes), - azimuth + angle, - elevation, - nframes ); - } - else - { - _early_panner->run_stereo( (sample_t*)audio_input[0].buffer(), - (sample_t*)audio_input[1].buffer(), - (sample_t*)aux_audio_output[1].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[2].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[3].jack_port()->buffer(nframes), - (sample_t*)aux_audio_output[4].jack_port()->buffer(nframes), - azimuth + angle, - elevation, - width, - nframes ); - } - - { - use_gainbuf = early_gain_smoothing.apply( gainbuf, nframes, early_gain ); - - for ( int i = 1; i < 5; i++ ) - { - /* gain effects */ - if ( unlikely( use_gainbuf ) ) - buffer_apply_gain_buffer( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), gainbuf, nframes ); - else - buffer_apply_gain( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), nframes, early_gain ); - } - } - - float corrected_angle = fabs( angle ) - (fabs( width ) * 0.5f); - - if ( corrected_angle < 0.0f ) - corrected_angle = 0.0f; - - float cutoff_frequency = ( 1.0f / ( 1.0f + corrected_angle ) ) * 300000.0f; - - use_gainbuf = gain_smoothing.apply( gainbuf, nframes, gain ); - - for ( unsigned int i = 0; i < audio_input.size(); i++ ) - { - /* gain effects */ - if ( unlikely( use_gainbuf ) ) - buffer_apply_gain_buffer( (sample_t*)audio_input[i].buffer(), gainbuf, nframes ); - else - buffer_apply_gain( (sample_t*)audio_input[i].buffer(), nframes, gain ); - - /* frequency effects */ - _lowpass[i]->run_lowpass( (sample_t*)audio_input[i].buffer(), cutoff_frequency, nframes ); - - /* delay effects */ - if ( likely( speed_of_sound ) ) - { - if ( unlikely( use_delaybuf ) ) - _delay[i]->run( (sample_t*)audio_input[i].buffer(), delaybuf, 0, nframes ); - else - _delay[i]->run( (sample_t*)audio_input[i].buffer(), 0, delay_seconds, nframes ); - } - } - - /* now do direct outputs */ - if ( audio_input.size() == 1 ) - { - _panner->run_mono( (sample_t*)audio_input[0].buffer(), - (sample_t*)audio_output[0].buffer(), - (sample_t*)audio_output[1].buffer(), - (sample_t*)audio_output[2].buffer(), - (sample_t*)audio_output[3].buffer(), - azimuth, - elevation, - nframes ); - } - else - { - _panner->run_stereo( (sample_t*)audio_input[0].buffer(), - (sample_t*)audio_input[1].buffer(), - (sample_t*)audio_output[0].buffer(), - (sample_t*)audio_output[1].buffer(), - (sample_t*)audio_output[2].buffer(), - (sample_t*)audio_output[3].buffer(), - azimuth, - elevation, - width, - nframes ); - } -} - -void -Spatializer_Module::handle_control_changed ( Port *p ) -{ - if ( p == &control_input[6] ) - { - bool v = p->control_value(); - - control_input[7].hints.visible = v; - control_input[8].hints.visible = v; - control_input[9].hints.visible = v; - - DMESSAGE( "reloading" ); - if ( _editor ) - _editor->reload(); - } -} - -bool -Spatializer_Module::configure_inputs ( int n ) -{ - output_connection_handle->show(); - output_connection_handle->tooltip( "Late Reverb" ); - output_connection2_handle->show(); - output_connection2_handle->tooltip( "Early Reverb" ); - - int on = audio_input.size(); - - if ( n > on ) - { - for ( int i = n - on; i--; ) - { - { filter *o = new filter(); - o->sample_rate( sample_rate() ); - _lowpass.push_back( o ); - } - - { - filter *o = new filter(); - o->sample_rate( sample_rate() ); - _highpass.push_back( o ); - } - { - delay *o = new delay( max_distance / 340.29f ); - o->sample_rate( sample_rate() ); - _delay.push_back( o ); - } - - add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - } - } - else if ( n < on ) - { - - for ( int i = on - n; i--; ) - { - delete _lowpass.back(); - _lowpass.pop_back(); - delete _highpass.back(); - _highpass.pop_back(); - delete _delay.back(); - _delay.pop_back(); - - audio_input.pop_back(); - } - } - -// control_input[4].hints.visible = audio_input.size() == 2; - - control_input[4].hints.default_value = audio_input.size() == 2 ? 90.0f : 0.0f; - - if ( n == 0 ) - { - remove_aux_audio_outputs(); - audio_output.clear(); - audio_input.clear(); - } - else - { - if ( audio_output.size() != 4 ) - { - for ( int i = 0; i < 4; i++ ) - { - add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - } - } - - if ( aux_audio_output.size() != 5 ) - { - add_aux_audio_output( "late reverb", 0 ); - add_aux_audio_output( "early reverb", 0 ); - add_aux_audio_output( "early reverb", 1 ); - add_aux_audio_output( "early reverb", 2 ); - add_aux_audio_output( "early reverb", 3 ); - } - } - - _connection_handle_outputs[0][0] = 0; - _connection_handle_outputs[0][1] = 1; - _connection_handle_outputs[1][0] = 1; - _connection_handle_outputs[1][1] = aux_audio_output.size(); - - return true; -} diff --git a/mixer/src/Spatializer_Module.H b/mixer/src/Spatializer_Module.H deleted file mode 100644 index 45a4699..0000000 --- a/mixer/src/Spatializer_Module.H +++ /dev/null @@ -1,67 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "JACK_Module.H" -#include "dsp.h" -#include - -class filter; -class delay; -class ambisonic_panner; -class Spatializer_Module : public JACK_Module -{ - Value_Smoothing_Filter gain_smoothing; - Value_Smoothing_Filter delay_smoothing; - Value_Smoothing_Filter late_gain_smoothing; - Value_Smoothing_Filter early_gain_smoothing; - - std::vector _lowpass; - std::vector _highpass; - std::vector _delay; - - ambisonic_panner *_panner; - ambisonic_panner *_early_panner; - -public: - - virtual const char *name ( void ) const { return "Spatializer"; } - - int can_support_inputs ( int n ) { return n > 0 && n < 3 ? 4 : -1; } - - virtual bool configure_inputs ( int n ); - - Spatializer_Module ( ); - virtual ~Spatializer_Module ( ); - - LOG_CREATE_FUNC( Spatializer_Module ); - - MODULE_CLONE_FUNC(Spatializer_Module); - - virtual void handle_sample_rate_change ( nframes_t n ); - virtual void handle_control_changed ( Port *p ); - virtual void draw ( void ); - -protected: - - virtual void process ( nframes_t nframes ); - -}; - diff --git a/mixer/src/SpectrumView.C b/mixer/src/SpectrumView.C deleted file mode 100644 index bfd5792..0000000 --- a/mixer/src/SpectrumView.C +++ /dev/null @@ -1,370 +0,0 @@ -/*******************************************************************************/ -/* Copyright (C) 2013 Mark McCurry */ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "SpectrumView.H" -#include -#include - -#include - -#include -#include -#include -#include - -#include - -static std::map _cached_plan; - -float SpectrumView::_fmin = 0; -float SpectrumView::_fmax = 0; -unsigned int SpectrumView::_sample_rate = 0; - -void -SpectrumView::clear_bands ( void ) -{ - if ( _bands ) - delete[] _bands; - - _bands = NULL; -} - -void -SpectrumView::data ( float *data, unsigned int nframes ) -{ - if ( _data ) - delete[] _data; - - _data = data; - _nframes = nframes; - - clear_bands(); - - redraw(); -} - -void -SpectrumView::clear_plans ( void ) -{ - /* invalidate all plans */ - - for ( std::map::iterator i = _cached_plan.begin(); - i != _cached_plan.end(); - i++ ) - { - delete[] i->second; - } - - _cached_plan.clear(); -} - -void -SpectrumView::sample_rate ( unsigned int sample_rate ) -{ - if ( _sample_rate != sample_rate ) - { - _sample_rate = sample_rate; - _fmin = 10; - /* _fmax = 28000; */ - /* /\* if ( _fmax > _sample_rate * 0.5f ) *\/ */ - _fmax = _sample_rate * 0.5f; - - clear_plans(); - } -} - - -#define min(a,b) (a b=log(Fmin)/log(10) - // log10(Fmax)=a+b -> a=log(Fmax)/log(10)-b - - const float b = logf(Fmin)/logf(10); - const float a = logf(Fmax)/logf(10)-b; - - //Evaluate at set frequencies - const float one_over_samples = 1.0f / samples; - const float one_over_samplerate = 1.0f / Fs; - - for(unsigned i=0; i -0.001) - { - fl_line(xloc*W+x(), y(), xloc*W+x(), y()+H); - - if ( j == 1 || j == 2 || j == 5 ) - { - sprintf(label, "%0.f%s", freq < 1000.0 ? freq : freq / 1000.0, freq < 1000.0 ? "" : "k" ); - int sx = x() + xloc*W + 1; - if ( sx < x() * W - 20 ) - fl_draw(label, sx, y()+h()); - } - } - } - } - - /* draw 0dB line */ - { - fl_line_style(FL_DASH,0); - float i = ((_dbmax-_dbmin)+_dbmin) / (_dbmax-_dbmin); - - int level = y()+H*i; - - fl_color(fl_color_add_alpha(fl_rgb_color(240,240,240), 60 )); - fl_line(x(), level, x()+W, level); - fl_line_style(FL_SOLID,0); - } -} - -void -SpectrumView::draw_curve ( void ) -{ - if ( !_bands ) - return; - - int W = w() - padding_right; - - //Build lines - float inc = 1.0f / (float)W; - - float fx = 0; - for( int i = 0; i < W; i++, fx += inc ) - fl_vertex(fx, 1.0f - _bands[i]); -} - -void -SpectrumView::draw ( void ) -{ - //Clear Widget - Fl_Box::draw(); - - int W = w() - padding_right; - int H = h() - padding_bottom; - - if ( !_bands ) { - analyze_data( W ); - } - - //Draw grid - fl_color(fl_color_add_alpha(fl_rgb_color( 100,100,100), 50 )); - - draw_semilog(); - - fl_push_clip( x(),y(),W,H); - - - fl_color(fl_color_add_alpha( selection_color(), 20 )); - - fl_push_matrix(); - fl_translate( x(), y() + 2 ); - fl_scale( W,H- 2 ); - - fl_begin_polygon(); - - fl_vertex(0.0,1.0); - - draw_curve(); - - fl_vertex(1.0,1.0); - - fl_end_polygon(); - - fl_color(fl_color_add_alpha( selection_color(), 100 )); - fl_begin_line(); - fl_line_style(FL_SOLID,2); - - /* fl_vertex(0.0,1.0); */ - - draw_curve(); - - /* fl_vertex(1.0,1.0); */ - - fl_end_line(); - - fl_pop_matrix(); - - fl_line_style(FL_SOLID,0); - - fl_pop_clip(); -} - -void -SpectrumView::resize ( int X, int Y, int W, int H ) -{ - if ( W != w() ) - clear_bands(); - - Fl_Box::resize(X,Y,W,H); -} - diff --git a/mixer/src/SpectrumView.H b/mixer/src/SpectrumView.H deleted file mode 100644 index 21200a5..0000000 --- a/mixer/src/SpectrumView.H +++ /dev/null @@ -1,64 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Mark McCurry */ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -class SpectrumView : public Fl_Box -{ - static unsigned int _sample_rate; - static float _fmin; - static float _fmax; - unsigned int _nframes; - - float * _data; - float * _bands; - float _dbmin; - float _dbmax; - bool _auto_level; - - void draw_curve ( void ); - void draw_semilog ( void ); - void analyze_data ( unsigned int plan_size ); - void clear_bands ( void ); - static void clear_plans ( void ); - -public: - - static void sample_rate ( unsigned int sample_rate ); - - /* set dB range. If min == max, then auto leveling will be enabled */ - void db_range ( float min, float max ) - { - _dbmin = min; - _dbmax = max; - _auto_level = min == max; - } - - /** /data/ must point to allocated memory. It will be freed when new data is set or when the control is destroyed */ - - void data ( float *data, unsigned int data_frames ); - - SpectrumView ( int X, int Y, int W, int H, const char *L=0 ); - virtual ~SpectrumView ( ); - - virtual void resize ( int X, int Y, int W, int H ); - virtual void draw ( void ); -}; - diff --git a/mixer/src/const.h b/mixer/src/const.h deleted file mode 100644 index 1cccaee..0000000 --- a/mixer/src/const.h +++ /dev/null @@ -1,24 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#define APP_NAME "Non-Mixer" -#define APP_TITLE "The Non-Mixer" -#define __MODULE__ "non-mixer" diff --git a/mixer/src/main.C b/mixer/src/main.C deleted file mode 100644 index 4e56e02..0000000 --- a/mixer/src/main.C +++ /dev/null @@ -1,327 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "Thread.H" -#include "debug.h" - -#include "Mixer.H" -#include "Project.H" - -#include "Loggable.H" - -/* for registration */ -#include "Module.H" -#include "Gain_Module.H" -#include "Spatializer_Module.H" -#include "Plugin_Module.H" -#include "JACK_Module.H" -#include "Meter_Module.H" -#include "Meter_Indicator_Module.H" -#include "Controller_Module.H" -#include "Mono_Pan_Module.H" -#include "Chain.H" -#include "Mixer_Strip.H" -#include "AUX_Module.H" -#include "NSM.H" -#include "Spatialization_Console.H" -#include "Group.H" - -#include -#include - -#include "FL/Fl.H" -#include "FL/x.H" -#include "FL/Fl_PNG_Image.H" - -/* TODO: put these in a header */ -#define USER_CONFIG_DIR ".non-mixer/" - -const double NSM_CHECK_INTERVAL = 0.25f; - -const char COPYRIGHT[] = "Copyright (c) 2008-2013 Jonathan Moore Liles"; - -char *user_config_dir; -Mixer *mixer; -NSM_Client *nsm; - -char *instance_name; - -#include - -static int -ensure_dirs ( void ) -{ - asprintf( &user_config_dir, "%s/%s", getenv( "HOME" ), USER_CONFIG_DIR ); - - int r = mkdir( user_config_dir, 0777 ); - - return r == 0 || errno == EEXIST; -} - -#include - -static void cb_main ( Fl_Double_Window *, void *) -{ - if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape ) - return; - - mixer->command_quit(); -} - -void -check_nsm ( void * v ) -{ - nsm->check(); - Fl::repeat_timeout( NSM_CHECK_INTERVAL, check_nsm, v ); -} - -static volatile int got_sigterm = 0; - -void -sigterm_handler ( int ) -{ - got_sigterm = 1; -} - -void -check_sigterm ( void * ) -{ - if ( got_sigterm ) - { - MESSAGE( "Got SIGTERM, quitting..." ); - mixer->quit(); - } - Fl::repeat_timeout( 0.1f, check_sigterm ); -} - - -int -main ( int argc, char **argv ) -{ - bool no_ui = false; - - fl_display = 0; - - printf( "%s %s %s -- %s\n", APP_TITLE, VERSION, "", COPYRIGHT ); - - Thread::init(); - - Thread thread( "UI" ); - thread.set(); - - ensure_dirs(); - - signal( SIGTERM, sigterm_handler ); - signal( SIGHUP, sigterm_handler ); - signal( SIGINT, sigterm_handler ); - - Fl_Tooltip::color( FL_BLACK ); - Fl_Tooltip::textcolor( FL_YELLOW ); - Fl_Tooltip::size( 14 ); - Fl_Tooltip::hoverdelay( 0.1f ); - - - LOG_REGISTER_CREATE( Mixer_Strip ); - LOG_REGISTER_CREATE( Chain ); - LOG_REGISTER_CREATE( Plugin_Module ); - LOG_REGISTER_CREATE( Gain_Module ); - LOG_REGISTER_CREATE( Spatializer_Module ); - LOG_REGISTER_CREATE( Meter_Module ); - LOG_REGISTER_CREATE( JACK_Module ); - LOG_REGISTER_CREATE( Mono_Pan_Module ); - LOG_REGISTER_CREATE( Meter_Indicator_Module ); - LOG_REGISTER_CREATE( Controller_Module ); - LOG_REGISTER_CREATE( AUX_Module ); - LOG_REGISTER_CREATE( Spatialization_Console ); - LOG_REGISTER_CREATE( Group ); - - signal( SIGPIPE, SIG_IGN ); - - - const char *osc_port = NULL; - - nsm = new NSM_Client; - - instance_name = strdup( APP_NAME ); - bool instance_override = false; - - static struct option long_options[] = - { - { "help", no_argument, 0, '?' }, - { "instance", required_argument, 0, 'i' }, - { "osc-port", required_argument, 0, 'p' }, - { "no-ui", no_argument, 0, 'u' }, - { 0, 0, 0, 0 } - }; - - int option_index = 0; - int c = 0; - - - while ( ( c = getopt_long_only( argc, argv, "", long_options, &option_index ) ) != -1 ) - { - switch ( c ) - { - case 'p': - DMESSAGE( "Using OSC port %s", optarg ); - osc_port = optarg; - break; - case 'i': - DMESSAGE( "Using OSC port %s", optarg ); - free( instance_name ); - instance_name = strdup( optarg ); - instance_override = true; - break; - case 'u': - DMESSAGE( "Disabling user interface" ); - no_ui = true; - break; - case '?': - printf( "\nUsage: %s [--instance instance_name] [--osc-port portnum] [path_to_project]\n\n", argv[0] ); - exit(0); - break; - } - } - - { - char *name = strdup( argv[0] ); - char *n = basename( name ); - - if ( ! strcmp( n, "non-mixer-noui" ) ) - no_ui = true; - - free( name ); - } - - if ( ! no_ui ) - { - Fl::visual( FL_DOUBLE | FL_RGB ); - - Fl::visible_focus( 0 ); - - fl_register_images(); - } - - Fl::lock(); - - Fl_Double_Window *main_window; - - - { - Fl_Double_Window *o = main_window = new Fl_Double_Window( 800, 600, "Non Mixer" ); - { - main_window->xclass( APP_NAME ); - - { - Fl_Widget *o = mixer = new Mixer( 0, 0, main_window->w(), main_window->h(), NULL ); - Fl_Group::current()->resizable(o); - } - } - o->end(); - - o->size_range( main_window->w(), mixer->min_h(), 0, 0 ); - - o->callback( (Fl_Callback*)cb_main, main_window ); - - if ( ! no_ui ) - { - o->show( 0,0 ); - } - - } - - Plugin_Module::spawn_discover_thread(); - - mixer->init_osc( osc_port ); - - char *nsm_url = getenv( "NSM_URL" ); - - if ( nsm_url ) - { - if ( ! nsm->init( nsm_url ) ) - { - if ( instance_override ) - WARNING( "--instance option is not available when running under session management, ignoring." ); - - if ( optind < argc ) - WARNING( "Loading files from the command-line is incompatible with session management, ignoring." ); - - nsm->announce( APP_NAME, ":switch:dirty:", argv[0] ); - - /* if ( ! no_ui ) */ - /* { */ - // poll so we can keep OSC handlers running in the GUI thread and avoid extra sync - Fl::add_timeout( NSM_CHECK_INTERVAL, check_nsm, NULL ); - /* } */ - } - } - else - { - if ( optind < argc ) - { - MESSAGE( "Waiting for plugins..." ); - Plugin_Module::join_discover_thread(); - - MESSAGE( "Loading \"%s\"", argv[optind] ); - - if ( ! mixer->command_load( argv[optind] ) ) - { - fl_alert( "Error opening project specified on commandline" ); - } - } - } - - Fl::add_timeout( 0.1f, check_sigterm ); - Fl::dnd_text_ops( 0 ); - - if ( ! no_ui ) - { - DMESSAGE( "Running UI..." ); - - Fl::run(); - } - else - { - DMESSAGE( "Not Running UI..." ); - while ( ! got_sigterm ) - { - Fl::wait(2147483.648); /* magic number means forever */ - } - } - - delete main_window; - main_window = NULL; - - MESSAGE( "Your fun is over" ); -} diff --git a/mixer/src/midi-mapper.C b/mixer/src/midi-mapper.C deleted file mode 100644 index bd2f31a..0000000 --- a/mixer/src/midi-mapper.C +++ /dev/null @@ -1,816 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2013 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include -#include -#include "debug.h" - -#include -#include - -using namespace MIDI; - -#include -#include - -#include -#include - -#include -#include - -#include -#include /* usleep */ -/* simple program to translate from MIDI<->OSC Signals using a fixed mapping */ - -#include - -#undef APP_NAME -const char *APP_NAME = "non-midi-mapper"; -#undef APP_TITLE -const char *APP_TITLE = "Non-MIDI-Mapper"; -#undef VERSION -const char *VERSION = "1.0"; - -nsm_client_t *nsm; -char *instance_name; - - -OSC::Endpoint *osc = 0; -/* const double NSM_CHECK_INTERVAL = 0.25f; */ - - -void -handle_hello ( lo_message msg ) -{ - int argc = lo_message_get_argc( msg ); - lo_arg **argv = lo_message_get_argv( msg ); - - if ( argc >= 4 ) - { - const char *url = &argv[0]->s; - const char *name = &argv[1]->s; - const char *version = &argv[2]->s; - const char *id = &argv[3]->s; - - MESSAGE( "Discovered NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - - /* register peer */ - osc->handle_hello( id, url ); - } -} - -void -check_nsm ( void ) -{ - nsm_check_nowait( nsm ); - // Fl::repeat_timeout( NSM_CHECK_INTERVAL, &check_nsm, v ); -} - -static int -osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ) -{ - handle_hello( msg ); - return 0; -} - - -static void -say_hello ( void ) -{ - if ( nsm_is_active( nsm ) ) - { - lo_message m = lo_message_new(); - - lo_message_add( m, "sssss", - "/non/hello", - osc->url(), - APP_TITLE, - VERSION, - instance_name ); - - nsm_send_broadcast( nsm, m ); - } -} - -class Engine : public JACK::Client -{ -public: - jack_ringbuffer_t *input_ring_buf; - jack_ringbuffer_t *output_ring_buf; - JACK::Port *midi_input_port; - JACK::Port *midi_output_port; - - Engine ( ) - { - input_ring_buf = jack_ringbuffer_create( 16 * 16 * sizeof( jack_midi_event_t )); - jack_ringbuffer_reset( input_ring_buf ); - output_ring_buf = jack_ringbuffer_create( 16 * 16 * sizeof( jack_midi_event_t )); - jack_ringbuffer_reset( output_ring_buf ); - - midi_input_port = 0; - midi_output_port = 0; - } - - virtual ~Engine ( ) - { - deactivate(); - } - - int process ( nframes_t nframes ) - { - /* process input */ - { - if ( !midi_input_port ) - return 0; - - void *buf = midi_input_port->buffer( nframes ); - - jack_midi_event_t ev; - - jack_nframes_t count = jack_midi_get_event_count( buf ); - - /* place MIDI events into ringbuffer for non-RT thread */ - - for ( uint i = 0; i < count; ++i ) - { -// MESSAGE( "Got midi input!" ); - - jack_midi_event_get( &ev, buf, i ); - - /* /\* time is frame within cycle, convert to absolute tick *\/ */ - /* e.timestamp( ph + (ev.time / transport.frames_per_tick) ); */ - /* e.status( ev.buffer[0] ); */ - /* e.lsb( ev.buffer[1] ); */ - /* if ( ev.size == 3 ) */ - /* e.msb( ev.buffer[2] ); */ - - if ( jack_ringbuffer_write( input_ring_buf, (char*)&ev, sizeof( jack_midi_event_t ) ) != sizeof( jack_midi_event_t ) ) - WARNING( "input buffer overrun" ); - } - } - - /* process output */ - { - void *buf = midi_output_port->buffer(nframes); - - jack_midi_clear_buffer( buf ); - - jack_midi_event_t ev; - - nframes_t frame = 0; - - while ( true ) - { - /* jack_ringbuffer_data_t vec[2]; */ - /* jack_ringbuffer_get_read_vector( output_ring_buf, vec ); */ - - if ( jack_ringbuffer_peek( output_ring_buf, (char*)&ev, sizeof( jack_midi_event_t )) <= 0 ) - break; - - unsigned char *buffer = jack_midi_event_reserve( buf, frame, ev.size ); - if ( !buffer ) - { - WARNING("Output buffer overrun, will send later" ); - break; - } - - memcpy( buffer, &ev, ev.size ); - - jack_ringbuffer_read_advance( output_ring_buf, sizeof( jack_midi_event_t ) ); - } - } - - return 0; - } - - - void freewheel ( bool starting ) - { - } - - int xrun ( void ) - { - return 0; - } - - int buffer_size ( nframes_t nframes ) - { - return 0; - } - - void shutdown ( void ) - { - } - - void thread_init ( void ) - { - } - -}; - -Engine *engine; - -const float MAX_NRPN = 16383.0f; - -static char -get_lsb( int i ) -{ - return i & 0x7F; -} - -static char -get_msb( int i ) -{ - return ( i >> 7 ) & 0x7F; -} - -static int -get_14bit ( char msb, char lsb ) - { - return msb * 128 + lsb; - } - -class signal_mapping -{ -public: - - bool is_nrpn; - // int nrpn; - - midievent event; - - std::string signal_name; - - OSC::Signal *signal; - - signal_mapping ( ) - { - is_nrpn = false; - signal = NULL; - } - - ~signal_mapping ( ) - { - if ( signal ) - delete signal; - signal = NULL; - } - - char *serialize ( void ) const - { - char *s; - const char *opcode = 0; - int v1 = 0; - - if ( is_nrpn ) - { - opcode = "NRPN"; - v1 = get_14bit( event.msb(), event.lsb() ); - } - else - switch ( event.opcode() ) - { - case MIDI::midievent::CONTROL_CHANGE: - opcode = "CC"; - v1 = event.lsb(); - break; - case MIDI::midievent::NOTE_ON: - opcode = "NOTE_ON"; - v1 = event.note(); - break; - default: - // unsupported - break; - } - - asprintf( &s, "%s %d %d", opcode, event.channel(), v1 ); - - return s; - } - - void deserialize ( const char *s ) - { - int channel; - char *opcode; - int control; - - if ( 3 == sscanf( s, "%ms %d %d", &opcode, &channel, &control ) ) - { - event.channel( channel ); - event.opcode( MIDI::midievent::CONTROL_CHANGE ); - - is_nrpn = 0; - - if ( !strcmp( opcode, "NRPN" ) ) - { - is_nrpn = 1; - - event.lsb( get_lsb( control )); - event.msb( get_msb( control )); - } - else if ( !strcmp( opcode, "CC" ) ) - { - event.lsb( control ); - } - - free(opcode); - } - } - -}; - -int signal_handler ( float value, void *user_data ) -{ - signal_mapping *m = (signal_mapping*)user_data; - - if ( m->is_nrpn ) - { - jack_midi_event_t jev[4]; - { - midievent e; - e.opcode( MIDI::midievent::CONTROL_CHANGE ); - e.channel( m->event.channel() ); - e.lsb( 99 ); - e.msb( m->event.msb() ); - jev[0].size = e.size(); - e.raw( (byte_t*)&jev[0], e.size() ); -// e.pretty_print(); - } - - { - midievent e; - e.opcode( MIDI::midievent::CONTROL_CHANGE ); - e.channel( m->event.channel() ); - e.lsb( 98 ); - e.msb( m->event.lsb() ); - jev[1].size = e.size(); - e.raw( (byte_t*)&jev[1], e.size() ); -// e.pretty_print(); - } - - - { - midievent e; - e.opcode( MIDI::midievent::CONTROL_CHANGE ); - e.channel( m->event.channel() ); - e.lsb( 6 ); - e.msb( int(value * MAX_NRPN ) >> 7 ); - jev[2].size = e.size(); - e.raw( (byte_t*)&jev[2], e.size() ); -// e.pretty_print(); - } - - { - midievent e; - e.opcode( MIDI::midievent::CONTROL_CHANGE ); - e.channel( m->event.channel() ); - e.lsb( 38 ); - e.msb( int( value * MAX_NRPN ) & 0x7F ); - jev[3].size = e.size(); - e.raw( (byte_t*)&jev[3], e.size() ); -// e.pretty_print(); - } - - for ( int i = 0; i < 4; i++ ) - { - if ( jack_ringbuffer_write( engine->output_ring_buf, (char*)&jev[i], - sizeof( jack_midi_event_t ) ) != sizeof( jack_midi_event_t ) ) - WARNING( "output buffer overrun" ); - } - } - else - { - jack_midi_event_t ev; - - m->event.msb( value * 127.0f ); - ev.size = m->event.size(); - m->event.raw( (byte_t*)&ev, m->event.size() ); - -// m->event.pretty_print(); - - if ( jack_ringbuffer_write( engine->output_ring_buf, (char*)&ev, sizeof( jack_midi_event_t ) ) != sizeof( jack_midi_event_t ) ) - WARNING( "output buffer overrun" ); - } - - return 0; -} - - -std::map sig_map; - -bool -save_settings ( void ) -{ - FILE *fp = fopen( "signals", "w" ); - - if ( !fp ) - return false; - - for ( std::map::const_iterator i = sig_map.begin(); - i != sig_map.end(); - i++ ) - { - fprintf( fp, "[%s] %s\n", i->first.c_str(), i->second.signal_name.c_str() ); - } - - fclose(fp); - - return true; -} - - -bool -load_settings ( void ) -{ - FILE *fp = fopen( "signals", "r" ); - - if ( !fp ) - return false; - - sig_map.clear(); - - char *signal_name; - char *midi_event; - - while ( 2 == fscanf( fp, "[%m[^]]] %m[^\n]\n", &midi_event, &signal_name ) ) - { - DMESSAGE( "%s, %s", midi_event, signal_name ); - - if ( sig_map.find( midi_event ) == sig_map.end() ) - { - signal_mapping m; - - m.deserialize( midi_event ); - - sig_map[midi_event] = m; - sig_map[midi_event].signal_name = signal_name; - sig_map[midi_event].signal = osc->add_signal( signal_name, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[midi_event] ); - } - - free(signal_name); - free(midi_event); - - /* if ( sig_map.find( s ) == sig_map.end() ) */ - /* { */ - /* int channel, control; */ - - /* if ( 2 == sscanf( s, "/midi/%d/CC/%d", &channel, &control ) ) */ - /* { */ - /* signal_mapping m; */ - - /* m.event.channel( channel ); */ - /* m.event.opcode( MIDI::midievent::CONTROL_CHANGE ); */ - /* m.event.lsb( control ); */ - - /* MESSAGE( "creating signal %s", s ); */ - /* sig_map[s] = m; */ - - /* sig_map[s].signal = osc->add_signal( s, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[s] ); */ - - /* } */ - /* if ( 2 == sscanf( s, "/midi/%d/NRPN/%d", &channel, &control ) ) */ - /* { */ - /* signal_mapping m; */ - - /* m.event.channel( channel ); */ - /* m.event.opcode( MIDI::midievent::CONTROL_CHANGE ); */ - /* m.event.lsb( get_lsb( control ) ); */ - /* m.event.msb( get_msb( control ) ); */ - - /* m.is_nrpn = true; */ - - /* MESSAGE( "creating signal %s", s ); */ - /* sig_map[s] = m; */ - - /* sig_map[s].signal = osc->add_signal( s, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[s] ); */ - - /* } */ - /* else */ - /* WARNING( "Could not decode signal spec \"%s\"", s ); */ - /* } */ - - /* free(s); */ - } - - return true; -} - -static bool -create_engine ( void ) -{ - if ( engine ) - { - delete engine->midi_input_port; - delete engine->midi_output_port; - delete engine; - } - - DMESSAGE( "Creating JACK engine" ); - - engine = new Engine(); - - if ( ! engine->init( instance_name ) ) - { - WARNING( "Failed to create JACK client" ); - return false; - } - - engine->midi_input_port = new JACK::Port( engine, NULL, "midi-in", JACK::Port::Input, JACK::Port::MIDI ); - engine->midi_output_port = new JACK::Port( engine, NULL, "midi-out", JACK::Port::Output, JACK::Port::MIDI ); - - if ( !engine->midi_input_port->activate() ) - { - WARNING( "Failed to activate JACK port" ); - return false; - } - - if ( !engine->midi_output_port->activate() ) - { - WARNING( "Failed to activate JACK port" ); - return false; - } - - return true; -} - - -static int -command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg, void *userdata ) -{ - if ( instance_name ) - free( instance_name ); - - instance_name = strdup( client_id ); - - osc->name( client_id ); - - mkdir( name, 0777 ); - chdir( name ); - - if ( ! create_engine() ) - { - return ERR_GENERAL; - } - - load_settings(); - - say_hello(); - - return ERR_OK; -} - -static int -command_save ( char **out_msg, void *userdata ) -{ - if ( save_settings() ) - { - nsm_send_is_clean(nsm); - return ERR_OK; - } - else - return ERR_GENERAL; -} - -static int -command_broadcast ( const char *path, lo_message msg, void *userdata ) -{ - lo_message_get_argc( msg ); -// lo_arg **argv = lo_message_get_argv( msg ); - - if ( !strcmp( path, "/non/hello" ) ) - { - handle_hello( msg ); - return 0; - } - else - return -1; - -} - -struct nrpn_state -{ - char control_msb; - char control_lsb; - char value_msb; - char value_lsb; - bool decending; -}; - -static -struct nrpn_state * -decode_nrpn ( nrpn_state *state, midievent e, int *take_action ) -{ - nrpn_state *n = &state[e.channel()]; - - *take_action = 0; - - switch ( e.lsb() ) - { - case 6: - if ( e.msb() < n->value_msb ) - n->value_lsb = 127; - else if ( e.msb() > n->value_msb ) - n->value_lsb = 0; - - n->value_msb = e.msb(); - *take_action = 1; - return n; - case 38: - n->value_lsb = e.msb(); - *take_action = 1; - return n; - case 99: - n->control_msb = e.msb(); - n->control_lsb = 0; - return n; - case 98: - n->control_lsb = e.msb(); - return n; - } - - return NULL; -} - - -static volatile int got_sigterm = 0; - -void -sigterm_handler ( int ) -{ - got_sigterm = 1; -} - -int -main ( int argc, char **argv ) -{ - nrpn_state nrpn_state[16]; - - signal( SIGTERM, sigterm_handler ); - signal( SIGHUP, sigterm_handler ); - signal( SIGINT, sigterm_handler ); - - nsm = nsm_new(); -// set_nsm_callbacks( nsm ); - - nsm_set_open_callback( nsm, command_open, 0 ); - nsm_set_broadcast_callback( nsm, command_broadcast, 0 ); - nsm_set_save_callback( nsm, command_save, 0 ); - - char *nsm_url = getenv( "NSM_URL" ); - - if ( nsm_url ) - { - if ( ! nsm_init( nsm, nsm_url ) ) - { - nsm_send_announce( nsm, APP_TITLE, ":dirty:", basename( argv[0] ) ); - - /* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */ -// Fl::add_timeout( NSM_CHECK_INTERVAL, check_nsm, NULL ); - } - } - - osc = new OSC::Endpoint(); - - osc->init( LO_UDP, NULL ); - - osc->add_method( "/non/hello", "ssss", osc_non_hello, osc, "" ); - - MESSAGE( "OSC URL = %s", osc->url() ); - - /* now we just read from the MIDI ringbuffer and output OSC */ - - DMESSAGE( "waiting for events" ); - - static int max_signal = 1; - - jack_midi_event_t ev; - midievent e; - while ( ! got_sigterm ) - { - osc->wait(20); - check_nsm(); - - if ( ! engine ) - continue; - - while ( jack_ringbuffer_read( engine->input_ring_buf, (char *)&ev, sizeof( jack_midi_event_t ) ) ) - { - e.timestamp( ev.time ); - e.status( ev.buffer[0] ); - e.lsb( ev.buffer[1] ); - if ( ev.size == 3 ) - e.msb( ev.buffer[2] ); - - switch ( e.opcode() ) - { - case MIDI::midievent::CONTROL_CHANGE: - case MIDI::midievent::PITCH_WHEEL: - { - int is_nrpn = 0; - - struct nrpn_state *st = decode_nrpn( nrpn_state, e, &is_nrpn ); - - if ( st != NULL && !is_nrpn ) - continue; - - char *midi_event; - - if ( is_nrpn ) - { - asprintf( &midi_event, "NRPN %d %d", e.channel(), get_14bit( st->control_msb, st->control_lsb )); - } - else if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE ) - asprintf( &midi_event, "CC %d %d", e.channel(), e.lsb() ); - /* else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL ) */ - /* asprintf( &s, "/midi/%i/PB", e.channel() ); */ - else - break; - - if ( sig_map.find( midi_event ) == sig_map.end() ) - { - char *s; - - asprintf( &s, "/control/%i", max_signal++ ); - - signal_mapping m; - - m.event.opcode( e.opcode() ); - m.event.channel( e.channel() ); - - m.event.lsb( e.lsb() ); - m.event.msb( e.msb() ); - - m.is_nrpn = is_nrpn; - - if ( is_nrpn ) - { - m.event.lsb( st->control_lsb ); - m.event.msb( st->control_msb ); - } - - /* if ( is_nrpn ) */ - /* m.nrpn = nrpnc_msb * 127 + nrpnc_lsb; */ - - MESSAGE( "creating signal %s", s ); - sig_map[midi_event] = m; - sig_map[midi_event].signal_name = s; - sig_map[midi_event].signal = osc->add_signal( s, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[midi_event] ); - - nsm_send_is_dirty( nsm ); - - free(s); - } - - float val = 0; - - if ( is_nrpn ) - { - val = get_14bit( st->value_msb, st->value_lsb ) / MAX_NRPN; - - } - else if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE ) - val = e.msb() / 127.0f; - else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL ) - val = e.pitch() / MAX_NRPN; - -// MESSAGE( "sending signal for %s = %f", s, val ); - - sig_map[midi_event].signal->value( val ); - - free( midi_event ); - - break; - } - default: - break; - } -// e.pretty_print(); - } - - -// usleep( 500 ); - } - - delete engine; - - return 0; -} diff --git a/mixer/wscript b/mixer/wscript deleted file mode 100644 index 2094e37..0000000 --- a/mixer/wscript +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python -import subprocess -import waflib.Options as Options -import string -import os - -# Version of this package (even if built as a child) -PACKAGE_VERSION = '1.2.0' - -# Variables for 'waf dist' -APPNAME = 'non-mixer' -VERSION = PACKAGE_VERSION - -# Mandatory variables -top = '.' -out = 'build' - -def options(opt): - opt.load('compiler_c') - opt.load('compiler_cxx') - opt.load('gnu_dirs') - -def configure(conf): - conf.load('compiler_c') - conf.load('compiler_cxx') - conf.load('gnu_dirs') - - conf.check(header_name='ladspa.h', define_name='HAVE_LADSPA_H', mandatory=True) - conf.check_cfg(package='lrdf', uselib_store='LRDF',args="--cflags --libs", - atleast_version='0.4.0', mandatory=True) - - conf.define('VERSION', PACKAGE_VERSION) - conf.define('SYSTEM_PATH', '/'.join( [ conf.env.DATADIR, APPNAME ] ) ) - conf.define('DOCUMENT_PATH', '/'.join( [ conf.env.DATADIR, 'doc' ] ) ) - conf.define('PIXMAP_PATH', '/'.join( [ conf.env.DATADIR, 'pixmaps' ] ) ) - - conf.write_config_header('config.h', remove=False) - - print('') - -def build(bld): - - libs = '' - - bld.program( source = ''' -src/Chain.C -src/Controller_Module.C -src/DPM.C -src/Gain_Module.C -src/Spatializer_Module.C -src/JACK_Module.C -src/AUX_Module.C -src/LADSPAInfo.C -src/Meter_Indicator_Module.C -src/Meter_Module.C -src/Mixer.C -src/Mixer_Strip.C -src/Module.C -src/Module_Parameter_Editor.C -src/Mono_Pan_Module.C -src/Plugin_Chooser_UI.fl -src/Plugin_Chooser.C -src/NSM.C -src/Panner.C -src/Plugin_Module.C -src/Project.C -src/Group.C -src/main.C -src/SpectrumView.C -src/Spatialization_Console.C -''', - target = 'non-mixer', - includes = ['.', 'src', '..', '../nonlib'], - use = ['nonlib', 'fl_widgets'], - uselib = [ 'JACK', 'LIBLO', 'LRDF', 'NTK', 'NTK_IMAGES', 'PTHREAD', 'DL', 'M' ], - install_path = '${BINDIR}') - - bld.program( source = 'src/midi-mapper.C', - target = 'non-midi-mapper', - includes = ['.', 'src', '..', '../nonlib'], - use = ['nonlib', 'fl_widgets'], - uselib = [ 'JACK', 'LIBLO', 'LRDF', 'NTK', 'NTK_IMAGES', 'PTHREAD', 'DL', 'M' ], - install_path = '${BINDIR}') - - bld( features = 'subst', - source = 'non-mixer.desktop.in', - target = 'non-mixer.desktop', - encoding = 'utf8', - install_path = "${DATADIR}" + '/applications', - BIN_PATH = bld.env.BINDIR ) - - start_dir = bld.path.find_dir( 'icons/hicolor' ) - - bld.install_files('${DATADIR}/icons/hicolor', start_dir.ant_glob('**/*.png'), - cwd=start_dir, relative_trick=True) - - bld.install_as('${DATADIR}/pixmaps/' + APPNAME + '/icon-256x256.png', 'icons/hicolor/256x256/apps/' + APPNAME + '.png') - - start_dir = bld.path.find_dir( 'pixmaps' ) - - bld.install_files('${DATADIR}/pixmaps/' + APPNAME + '/', start_dir.ant_glob('*.png'), - cwd=start_dir, relative_trick=True) - - bld.install_files( '/'.join( [ '${DATADIR}/doc', APPNAME ] ), bld.path.ant_glob( 'doc/*.html doc/*.png' ) ) - - bld.symlink_as( '${BINDIR}/' + APPNAME + '-noui', APPNAME ) diff --git a/sequencer/COPYING b/sequencer/COPYING deleted file mode 100644 index d60c31a..0000000 --- a/sequencer/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/sequencer/doc/KEYS.html b/sequencer/doc/KEYS.html deleted file mode 100644 index c41c331..0000000 --- a/sequencer/doc/KEYS.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - -Key Bindings - - -
-

Key Bindings

-

-
-
-
- -

-
-
-

-These keys are in effect when the pattern or phrase editor grid is focused. -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Fig. 1. Editor Keybindings -
keyfunction
[previous
]next
1horizontal zoom out
2horizontal zoom in
3vertical zoom out
4vertical zoom in
ccreate
dduplicate
fmove to playhead
rselect range as defined by L and R cursors
qselect none
Ccrop to range
Deletedelete selected
Shift-Deleteclear grid
Control-Deletedelete time in range
Control-Insertinsert time
Arrow keysmove viewport
Ctrl-Leftmove to previous note
Ctrl-Rightmove to next note
<move selection left
>move selection right
,move selection up
.move selection down
ttrim length
Spacetoggle transport
mmute
ssolo
-
- - - - - - - -
-Fig. 2. Gloabl keybindings -
keyfunction
Alt-pSwitch to pattern editor
Alt-aSwitch to phrase editor
Alt-sSwitch to sequence editor
SpaceToggle transport
HomeLocate transport to frame 0
-

-Other functions are accessible from the menus or the key is otherwise indicated. -

-
- - diff --git a/sequencer/doc/KEYS.mu b/sequencer/doc/KEYS.mu deleted file mode 100644 index a96435b..0000000 --- a/sequencer/doc/KEYS.mu +++ /dev/null @@ -1,46 +0,0 @@ - -! title Key Bindings - --- - - These keys are in effect when the pattern or phrase editor grid is focused. - -// Editor Keybindings -[[ key, function -[[ [, previous -[[ ], next -[[ 1, horizontal zoom out -[[ 2, horizontal zoom in -[[ 3, vertical zoom out -[[ 4, vertical zoom in -[[ c, create -[[ d, duplicate -[[ f, move to playhead -[[ r, select range (as defined by L and R cursors) -[[ q, select none -[[ C, crop to range -[[ Delete, delete selected -[[ Shift-Delete, clear grid -[[ Control-Delete, delete time in range -[[ Control-Insert, insert time -[[ Arrow keys, move viewport -[[ Ctrl-Left, move to previous note -[[ Ctrl-Right, move to next note -[[ \<, move selection left -[[ >, move selection right -[[ \,, move selection up -[[ ., move selection down -[[ t, trim length -[[ Space, toggle transport -[[ m, mute -[[ s, solo - -// Gloabl keybindings -[[ key, function -[[ Alt-p, Switch to pattern editor -[[ Alt-a, Switch to phrase editor -[[ Alt-s, Switch to sequence editor -[[ Space, Toggle transport -[[ Home, Locate transport to frame 0 - - Other functions are accessible from the menus or the key is otherwise indicated. diff --git a/sequencer/doc/MANUAL.html b/sequencer/doc/MANUAL.html deleted file mode 100644 index 7cddb0c..0000000 --- a/sequencer/doc/MANUAL.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - -The Non Sequencer - - - -
-

The Non Sequencer

-

-
-Jonathan Moore Liles <male@tuxfamily.org>
-
- -

-
- -

1. Description

-
- -
fig.
-

1.1. Guiding Principles

-
  1. Flexibility -
  2. Efficiency -
  3. Purpose -
  4. Grace -

-Non has many modes and functions. Where flexibility comes at a small cost, we prefer to be flexible and make up the difference elsewhere. Where arbitrary limitations are reasonable and necessary, Non enforces them, but not without being forced into it. Where it is easier to be inefficient than efficient, but the efficiency matters, we prefer to put in the (small amount of) work required to be efficient, often resulting in thousand-fold performance gains; this may sound like an obvious statement, but, in fact, design for efficiency is a rare practice in this (Linux Audio'Modern' software arena. Although it is tempting to implement a kitchen sink in every program, we resist the urge. Non has the purpose of being a real-time sequencer and anything outside of that scope is a job for another day. If there is something related to the task at hand that a computer can do instantly and easily, but which requires labor for you, Non tries to do it for you so that you can continue making music without being bothered. Non's user interface is designed to combine the stark functionality and speed of hardware with the degrees of freedom of software. -

-

2. The Interface

-

-The interface is quite simple and is based on the excellent FLTK (1.1.x) toolkit. (Versions < 1 of Non were based on raw Xlib and a few Motif widgets.) The author examined many toolkits before beginning, and has absolutely no interest in pursuing GTK or Qt--Non simply doesn't require much of a toolkit, and these are incapable of providing less than total excess. -

-

-Non's GUI is highly optimized. Common operations are designed to be as fast as possible. Where other sequencers completely monopolize the CPU when scrolling, etc., Non performs smoothly--even on antiquated hardware. It is not technically difficult to achieve such speed. And, in fact, it is a shame that more developers don't consider good (or even just reasonable) performance a priority. -

-

2.1. The Pattern Editor

-
- -
fig.
-

-Upon invocation, Non enters the pattern editor and loads Pattern 1. The pattern editor presents a grid interface--the heart of a step sequencer. You can toggle a note on the grid by entering its coordinates with the keyboard or clicking an intersection with the mouse. The length of patterns is unlimited and no special action is required to lengthen them (simply adding notes beyond the "end" is enough.) Non can present grids in one of two modes, expanded and compacted. In the compacted view, only named rows are displayed; this means that only the notes the current instrument or scale will consume vertical space--resulting in far more efficient use of screen real-estate. Any notes that are made invisible by the compacted view will be silenced. -

-

-

-The resolution of the pattern display can be adjusted (the default is one point per 1/16th note), and, additionally, the canvas can be zoomed horizontally and vertically as necessary. However, it is highly recommended that you avoid creating 'vertical' compositions, that is, one should place each part in a separate pattern and avoid the need to scroll about looking for notes. -

-

-Tonic patterns have a choice of scale and key, which limits the display to only valid notes. This row-compaction can be turned off, if desired, so that all 128 notes are visible. Or simply choose the chromatic mapping if you are not creating scale based music. -

-

-Percussion, or other sample-based patterns can be assigned an instrument mapping, which again limits the display to only those notes for which names and volumes have been provided. The instrument definition format is a simple ASCII file containing one name, note and volume percentage per line. -

-

-Individual patterns may be soloed or muted right from the pattern editor. -

-

-Each pattern has a setting for output MIDI channel and sequencer port--and these may also be changed while the transport is running. -

-

2.1.1. The Notes

-

-The type (duration) of note to be inserted can be adjusted in the pattern editor (control+mouse-wheel). The velocity of individual notes may be adjusted (mouse-wheel), and the current value is reflected in the color of the note. Ranges may also be inserted and deleted, a commonly required operation during composition, but one that is, sadly, missing from many sequencers. -

-
- -
fig.
-

2.1.2. Recording

-

-A pattern can be recorded via MIDI in one of four modes: -

-
-
Merge (the most familiar/least useful)
-
In this mode recorded events are merged into the pattern on each pass through the loop. This is how most sequencers work, but it usually just results in a jumble of notes that require much manual cleaning up.
-
Overwrite (each pass [with input] replaces the previous contents of the pattern)
-
This is like merge mode, except that the pattern is cleared before the recorded events are input. If no notes have been played during a loop, the pattern remains unchanged. This is a great way to just get a part down without having to remove your hands from the instrument.
-
Layer (each pass [with input] goes into a new pattern)
-
This is just like overwrite mode, except that the pattern actually overwritten is a duplicate. Use this mode to record several loops of the same length without removing your hands from the instrument.
-
New
-
In this mode, all recorded events are placed into a new pattern (of whatever length) when recording is stopped.
-
-

2.1.3. The Event Editor

-
- -
fig.
-

-For situations requiring close inspection, fine-adjustments or entering of non-note data, the Event Editor allows one to edit the raw MIDI event list of a pattern. A common use is to insert program or control change events. -

-

-Like everything else in Non, the Event Editor is real-time--change a note and you'll see and hear the result as the pattern plays. -

-

2.2. The Phrase Editor

-
- -
fig.
-

-Phrases are to patterns as patterns are to notes. Switching to the Phrase Editor brings up Phrase 1, where each row corresponds to an existing pattern. The grid of the Phrase Editor is fixed at one column-per-beat. This view is somewhat similar to a timeline view in other sequencers, but do not be deceived--Phrases may be many in number and are triggered just like patterns. -

-

-When a node on the Phrase Editor grid is activated, the length of the cue event inserted will be the same as that of the pattern being triggered. Adjusting the duration of this event will cause the pattern be cut short or looped. If the length of a referenced pattern is changed, this will not be reflected in the Phrase display. You must either re-insert or adjust the length of the reference. -

-

-It is recommended that, to avoid confusion, you first compose all of the patterns you need for a phrase, and only then bring up the phrase editor. -

-

-Editing operations are the same as those for the Pattern Editor. -

-

2.3. The Sequence Editor

-

-The Sequence Editor defines the sequence of playback. The interface is a list of phrases, to be played sequentially, beginning from bar 1. It is not necessary to include all existing phrases in the playlist. Phrases can be moved up and down the playlist, inserted and deleted. The editor displays the start bar of each phrase in addition to its number and name. -

-

-This sequence->phrase->pattern hierarchy allows for logical, expressive compositions--without the labor intensive copypasteduplicate work-flow imposed by other sequencers. -

-

-For example, suppose you have a song with a 12 bar progression that repeats 4 times. This 12 bar sequence is composed of many patterns, each a few measures in length and roughly corresponding to the chords in the progression. -

-

-In another sequencer you would be required to use clumsy copy/paste operations to destructively extend the 12 bar sequence. Then if you wanted to change a part of that subsequence later, you would have to go edit each instance of it on the 'timeline' view. This is absurdly inefficient for the operator. -

-

-In Non you simply create your patterns, assemble them into logical phrases, and then assemble these phrases into a sequence that determines the entire song. This approach is similar to the bottom-up approach of factored languages such as Forth. -

-

2.4. Pattern Triggers

-
- -
fig.
-

-Next to the sequence playlist is an array of pattern triggers. Here one can monitor the progress of multiple patterns during playback and cause them to be muted etc. -

-

-The left mouse button toggles muting, the middle button toggles soloing, and the right button brings up the given pattern in the pattern editor. -

-

-Playing patterns appear green, the solo pattern appears red, and muted patterns appear gray, -

-

3. MIDI

-

3.1. IO

-

-Non utilizes the Jack MIDI transport. Jack MIDI is an emerging MIDI transport for Linux. Since Jack already provides similar routing as the ALSA Sequencer interface, little is lost--besides compatibility with existing programs. (Jack has an aseq bridge capability, but in order to benefit from Jack MIDI, both sequencer and synth must use Jack). The Jack MIDI API is extremely limited in comparison to the very capable ALSA API, but this is a problem for the programmer, not the user. -

-

-At the time of writing, Non is one of only two sequencers to use Jack MIDI natively. -

-

3.1.1. About Jack MIDI Connections

-

-Since Jack MIDI is new and not all programs support it, many find themselves confused. This section attempts to explain Jack MIDI ports. -

-

-The ALSA sequencer interface has long been the standard MIDI routing subsystem on Linux. But many (all) of the programs we use for synthesis these days use Jack for their audio IO. It makes more sense for those MIDI related programs utilizing the Jack Transport for synchronization to also use Jack ports for MIDI delivery. Therefore, ALSA MIDI is quickly becoming obsolete. -

-

-Jack MIDI ports are not related to ALSA MIDI ports in any way. Jack MIDI ports are just like Jack audio ports, except that the data being transmitted in each buffer are raw, timestamped MIDI events instead of floating point audio samples. Jack MIDI is sample-accurate. This means that a MIDI Note On event can occur concurrently with a sound, and the two will never drift apart as often happens to some extent with ALSA. -

-

-In essence, Jack MIDI is a way of expressing a direct temporal correlation between audio and MIDI data. -

-
- - -
Note:Older versions of QJackCtl and other connection managers do not -know about Jack MIDI ports. Please make sure you're using an -up-to-date version. -
-
-

-

-For example, to connect Non to ZynAddSubFX (the CVS version supports Jack MIDI), type the following into the shell: -

-
-
-$ jack_connect Non:midi_out-1 ZynAddSubFX:midi_in
-
-

-Also, be sure that Zyn's outputs are connected to system:playback_* so that you can hear the sounds it produces. -

-

-It is possible to use Jack MIDI clients and ALSA MIDI clients together via the bridge built into jackd. For this to work you must append the -X seq option to the alsa driver section of the jackd command line. Like so: -

-
-
-$ jackd -d alsa -X seq
-
-

-The way such bridged ports are named varies between Jack versions, but they should be fairly obvious. When used in this way, many of the advantages of Jack MIDI are lost, so it is recommended that you find a Jack MIDI capable synth for best results. -

-
- - - -
-Fig. 3.1. Example of Jack MIDI connections in Patchage -
fig. 3.1
-

3.2. Non Files

-

-The format of .non files is a variation of SMF-2. In an SMF-2 file, each track chunk represents a pattern. Because Non groups patterns into phrases, this usage of SMF-2 is probably not compatible with other implementations (although, the author has never actually seen another program that could play back SMF-2 anyway.) -

-

-Each phrase is stored as a track of MIDI Cue messages, each referring to a pattern to be triggered. The sequence/playlist is stored as the first track, and consists of a list of Cue Point meta-events referring to phrases. -

-

-Also in the first track is a sequencer specific meta-event (ID "Non!") containing song data that cannot be readily expressed with existing meta events, and some versioning info to aid future compatibility. -

-

-In short, the author has done the utmost to save sequences in a standard format--within reason; SMF was hardly designed with a program like Non in mind--instead of some ad-hoc ASCII format (which would have been far easier to implement), or worse, buggy, bulky, and unmaintainable XML. -

-

3.3. Exports

-

-In addition to saving and loading .non files, Non can export individual patterns as flat, SMF-0 MIDI files. -

-

3.4. Imports

-

-SMF-0 files can be imported as a new pattern (all channels merged), or SMF-1 (such as those written by Seq24) and SMF-2 (ever seen one of these?) can be imported as N new patterns (selected from a track list.) All imported patterns are set to display the Chromatic scale, in order that no notes be hidden from view. -

-

-This should make it easy to migrate any existing patterns that you may have over to Non, or to permit editing of Non patterns in external programs (for graphic controller tweaking perhaps?) -

-

4. Synchronization

-

-Non's transport is driven by the Jack Transport, so in order to sync Non with a DAW like Ardour, you must set Ardour to be the Jack Timebase Master. Therefore, all tempo mapping and time signature information should be manipulated in the Timebase Master--Non will respond to these changes automatically. If there is no Timebase Master registered when Non starts, it will take over that role instead. This is useful if you simply plan to use Non as a musical instrument. -

-

5. Control

-

-Non creates two MIDI input ports, one for performance data and one for control data. The control port is used to control Non with hardware MIDI controllers, such as the BCF2000, or other software. The performance port is used to record musical data into patterns. -

-

6. Playback

-

-The playback mode can be toggled between Pattern, Sequence and Trigger. In Pattern mode (the default), all patterns are played simultaneously, from the beginning, and looped forever. Since patterns may differ widely in length, interesting compositions are possible. In this mode, Non makes for a very intuitive software instrument--rivaled only by the excellent program FreeWheeling (a live audio looper.) -

-

-In Sequence mode, playback strictly follows the sequence list and the Jack transport, and does not loop. This mode is suitable for parallel compositions between Non and a Jack Timebase Master capable DAW. -

-

-Trigger mode is very much like Pattern mode, except that all patterns begin muted and must be enabled via the trigger view. -

-

7. Sister Projects

-

-Much of the inspiration to move forward with Non was derived from JP Mercury's highly useful and successful FreeWheeling looper. Mr. Mercury is a visionary. -

-

-But the closest sister of Non has to be the amazingly capable ZynAddSubFX soft-synth by Nasca Octavian Paul. ZynAddSubFX, like Non, utilizes the FLTK GUI toolkit, and has recently begun to support Jack MIDI (albeit in a limited fashion.) This is, hands down, the best synth available for Linux, and probably one of the best period. If all you have is Non and Zyn, you have all that you require to make great music. -

-

-Of course, this section can hardly go without mention of Rob Buse's Seq24. It was the author's unending frustration with the abysmal performance and absurd limitations of Seq24 that, more than any other single factor, inspired him to write Non. The most frustrating aspect was that, prior to Non, Seq24 was, in the author's opinion, the best sequencer available on Linux. Seq24, which claims to be light and free of bloat is, without comparison, the slowest, most poorly optimized sequencer the author has tried. Even the huge, snarling beast that is RoseGarden out performs Seq24 in every way but start time. -

-

-Those days are over. -

-
- - diff --git a/sequencer/doc/MANUAL.mu b/sequencer/doc/MANUAL.mu deleted file mode 100644 index b3564e4..0000000 --- a/sequencer/doc/MANUAL.mu +++ /dev/null @@ -1,391 +0,0 @@ - -! title The Non Sequencer -! author Jonathan Moore Liles #(email,male@tuxfamily.org) - --- Table Of Contents - -: Description - -< non-new-about.png - -:: Guiding Principles - -+ Flexibility -+ Efficiency -+ Purpose -+ Grace - - Non has many modes and functions. Where flexibility comes at a small - cost, we prefer to be flexible and make up the difference - elsewhere. Where arbitrary limitations are reasonable and necessary, - Non enforces them, but not without being forced into it. Where it is - easier to be inefficient than efficient, but the efficiency matters, - we prefer to put in the (small amount of) work required to be - efficient, often resulting in thousand-fold performance gains; this - may sound like an obvious statement, but, in fact, design for - efficiency is a rare practice in this (Linux Audio/'Modern' - software) arena. Although it is tempting to implement a kitchen sink - in every program, we resist the urge. Non has the purpose of being a - real-time sequencer and anything outside of that scope is a job for - another day. If there is something related to the task at hand that - a computer can do instantly and easily, but which requires labor for - you, Non tries to do it for you so that you can continue making - music without being bothered. Non's user interface is designed to - combine the stark functionality and speed of hardware with the - degrees of freedom of software. - -: The Interface - - The interface is quite simple and is based on the excellent FLTK - (1.1.x) toolkit. (Versions \< 1 of Non were based on raw Xlib and a - few Motif widgets.) The author examined many toolkits before - beginning, and has absolutely no interest in pursuing GTK or Qt--Non - simply doesn't require much of a toolkit, and these are incapable of - providing less than total excess. - - Non's GUI is highly optimized. Common operations are designed to be - as fast as possible. Where other sequencers completely monopolize - the CPU when scrolling, etc., Non performs smoothly--even on - antiquated hardware. It is not technically difficult to achieve - such speed. And, in fact, it is a shame that more developers don't - consider good (or even just reasonable) performance a priority. - -:: The Pattern Editor - -< non-pattern-editor.png - - Upon invocation, Non enters the pattern editor and loads Pattern - 1. The pattern editor presents a grid interface--the heart of a step - sequencer. You can toggle a note on the grid by entering its - coordinates with the keyboard or clicking an intersection with the - mouse. The length of patterns is unlimited and no special action is - required to lengthen them (simply adding notes beyond the "end" is - enough.) Non can present grids in one of two modes, expanded and - compacted. In the compacted view, only named rows are displayed; - this means that only the notes the current instrument or scale will - consume vertical space--resulting in far more efficient use of - screen real-estate. Any notes that are made invisible by the - compacted view will be silenced. - - You may add, remove, transpose, move, and edit notes, as well as - trigger/mute patterns, while the transport is running. - - The resolution of the pattern display can be adjusted (the default - is one point per 1\/16th note), and, additionally, the canvas can be - zoomed horizontally and vertically as necessary. However, it is - highly recommended that you avoid creating 'vertical' compositions, - that is, one should place each part in a separate pattern and avoid - the need to scroll about looking for notes. - - Tonic patterns have a choice of scale and key, which limits the - display to only valid notes. This /row-compaction/ can be turned - off, if desired, so that all 128 notes are visible. Or simply choose - the /chromatic/ mapping if you are not creating scale based music. - - Percussion, or other sample-based patterns can be assigned an - /instrument/ mapping, which again limits the display to only those - notes for which names and volumes have been provided. The instrument - definition format is a simple ASCII file containing one name, note - and volume percentage per line. - - Individual patterns may be soloed or muted right from the pattern - editor. - - Each pattern has a setting for output MIDI channel and sequencer - port--and these may also be changed while the transport is running. - -::: The Notes - - The type (duration) of note to be inserted can be adjusted in the - pattern editor (control+mouse-wheel). The velocity of individual - notes may be adjusted (mouse-wheel), and the current value is - reflected in the color of the note. Ranges may also be /inserted/ - and /deleted/, a commonly required operation during composition, but - one that is, sadly, missing from many sequencers. - -< non-cursors.png - -::: Recording - - A pattern can be recorded via MIDI in one of four modes: - -= Merge (the most familiar/least useful) - = In this mode recorded events are merged into the pattern on each pass - = through the loop. This is how most sequencers work, but it usually just - = results in a jumble of notes that require much manual cleaning up. -= Overwrite (each pass [with input] replaces the previous contents of the pattern) - = This is like merge mode, except that the pattern is cleared before - = the recorded events are input. If no notes have been played during - = a loop, the pattern remains unchanged. This is a great way to just get - = a part down without having to remove your hands from the instrument. -= Layer (each pass [with input] goes into a new pattern) - = This is just like overwrite mode, except that the pattern actually - = overwritten is a duplicate. Use this mode to record several loops of - = the same length without removing your hands from the instrument. -= New - = In this mode, all recorded events are placed into a new pattern (of - = whatever length) when recording is stopped. - -# It is especially useful if you bind Record to a MIDI footswitch. - -::: The Event Editor - -< non-event-editor-notes.png - - For situations requiring close inspection, fine-adjustments or - entering of non-note data, the Event Editor allows one to edit the - raw MIDI event list of a pattern. A common use is to insert program - or control change events. - - Like everything else in Non, the Event Editor is real-time--change a - note and you'll see and hear the result as the pattern plays. - -:: The Phrase Editor - -< non-phrase-editor.png - - Phrases are to patterns as patterns are to notes. Switching to the - Phrase Editor brings up Phrase 1, where each row corresponds to an - existing /pattern/. The grid of the Phrase Editor is fixed at one - column-per-beat. This view is somewhat similar to a timeline view in - other sequencers, but do not be deceived--Phrases may be many in - number and are triggered just like patterns. - - When a node on the Phrase Editor grid is activated, the length of - the cue event inserted will be the same as that of the pattern being - triggered. Adjusting the duration of this event will cause the - pattern be cut short or looped. If the length of a referenced - pattern is changed, this will *not* be reflected in the Phrase - display. You must either re-insert or adjust the length of the - reference. - - It is recommended that, to avoid confusion, you first compose all of - the patterns you need for a phrase, and only then bring up the - phrase editor. - - Editing operations are the same as those for the Pattern Editor. - -:: The Sequence Editor - - The Sequence Editor defines the sequence of playback. The interface - is a list of phrases, to be played sequentially, beginning from bar - 1. It is not necessary to include all existing phrases in the - playlist. Phrases can be moved up and down the playlist, inserted - and deleted. The editor displays the start bar of each phrase in - addition to its number and name. - - This sequence->phrase->pattern hierarchy allows for logical, - expressive compositions--without the labor intensive - copy/paste/duplicate work-flow imposed by other sequencers. - - For example, suppose you have a song with a 12 bar progression that - repeats 4 times. This 12 bar sequence is composed of many patterns, - each a few measures in length and roughly corresponding to the - chords in the progression. - - In another sequencer you would be required to use clumsy copy\/paste - operations to destructively extend the 12 bar sequence. Then if you - wanted to change a part of that subsequence later, you would have to - go edit each instance of it on the 'timeline' view. This is absurdly - inefficient for the operator. - - In Non you simply create your patterns, assemble them into logical - phrases, and then assemble these phrases into a sequence that - determines the entire song. This approach is similar to the - bottom-up approach of factored languages such as Forth. - - -:: Pattern Triggers - -< non-pattern-triggers.png - - Next to the sequence playlist is an array of pattern triggers. Here - one can monitor the progress of multiple patterns during playback - and cause them to be muted etc. - - The left mouse button toggles muting, the middle button toggles - soloing, and the right button brings up the given pattern in the - pattern editor. - - Playing patterns appear green, the solo pattern appears red, and - muted patterns appear gray, - -: MIDI - -:: IO - - Non utilizes the Jack MIDI transport. Jack MIDI is an emerging MIDI - transport for Linux. Since Jack already provides similar routing as - the ALSA Sequencer interface, little is lost--besides compatibility - with existing programs. (Jack has an aseq bridge capability, but in - order to benefit from Jack MIDI, both sequencer and synth must use - Jack). The Jack MIDI API is extremely limited in comparison to the - very capable ALSA API, but this is a problem for the programmer, not - the user. - - At the time of writing, Non is one of only two sequencers to use - Jack MIDI natively. - -::: About Jack MIDI Connections - - Since Jack MIDI is new and not all programs support it, many find - themselves confused. This section attempts to explain Jack MIDI - ports. - - The ALSA sequencer interface has long been the standard MIDI routing - subsystem on Linux. But many (all) of the programs we use for - synthesis these days use Jack for their audio IO. It makes more - sense for those MIDI related programs utilizing the Jack Transport - for synchronization to also use Jack ports for MIDI - delivery. Therefore, ALSA MIDI is quickly becoming obsolete. - - Jack MIDI ports are *not* related to ALSA MIDI ports in any - way. Jack MIDI ports are just like Jack audio ports, except that the - data being transmitted in each buffer are raw, timestamped MIDI - events instead of floating point audio samples. Jack MIDI is - sample-accurate. This means that a MIDI Note On event can occur - concurrently with a sound, and the two will never drift apart as - often happens to some extent with ALSA. - - In essence, Jack MIDI is a way of expressing a direct temporal - correlation between audio and MIDI data. - -// Note: -{ Older versions of QJackCtl and other connection managers do not -{ know about Jack MIDI ports. Please make sure you're using an -{ up-to-date version. - - When Non is started, it will create `Non:midi_in` and - `Non:control_in` input ports, as well as the 16 output ports with - names after the form `Non:midi_out-X`, where `X` is a number from 1 - to 16. These ports will be visible in any connection manager capable - of connecting Jack MIDI ports, as well as via the `jack_lsp` and - `jack_connect` command-line utilities. - - For example, to connect Non to ZynAddSubFX (the CVS version supports - Jack MIDI), type the following into the shell: - -> $ jack_connect Non:midi_out-1 ZynAddSubFX:midi_in - - Also, be sure that Zyn's outputs are connected to - system:playback\_\* so that you can hear the sounds it produces. - - It is possible to use Jack MIDI clients and ALSA MIDI clients - together via the bridge built into jackd. For this to work you must - append the `-X seq` option to the `alsa` driver section of the jackd - command line. Like so: - -> $ jackd -d alsa -X seq - - The way such bridged ports are named varies between Jack versions, - but they should be fairly obvious. When used in this way, many of - the advantages of Jack MIDI are lost, so it is recommended that you - find a Jack MIDI capable synth for best results. - -// Example of Jack MIDI connections in Patchage -< non-patchage.png - -:: Non Files - - The format of `.non` files is a variation of SMF-2. In an SMF-2 - file, each track chunk represents a pattern. Because Non groups - patterns into /phrases/, this usage of SMF-2 is probably not - compatible with other implementations (although, the author has - never actually seen another program that could play back SMF-2 - anyway.) - - Each phrase is stored as a track of MIDI Cue messages, each - referring to a pattern to be triggered. The sequence\/playlist is - stored as the first track, and consists of a list of Cue Point - meta-events referring to phrases. - - Also in the first track is a sequencer specific meta-event (ID - "Non!") containing song data that cannot be readily expressed with - existing meta events, and some versioning info to aid future - compatibility. - - In short, the author has done the utmost to save sequences in a - standard format--within reason; SMF was hardly designed with a - program like Non in mind--instead of some ad-hoc ASCII format (which - would have been *far* easier to implement), or worse, buggy, bulky, - and unmaintainable XML. - -:: Exports - - In addition to saving and loading `.non` files, Non can export - individual patterns as flat, SMF-0 MIDI files. - -:: Imports - - SMF-0 files can be imported as a new pattern (all channels merged), - or SMF-1 (such as those written by Seq24) and SMF-2 (ever seen one - of these?) can be imported as N new patterns (selected from a track - list.) All imported patterns are set to display the Chromatic scale, - in order that no notes be hidden from view. - - This should make it easy to migrate any existing patterns that you - may have over to Non, or to permit editing of Non patterns in - external programs (for graphic controller tweaking perhaps?) - -: Synchronization - - Non's transport is driven by the Jack Transport, so in order to sync - Non with a DAW like Ardour, you must set Ardour to be the Jack - Timebase Master. Therefore, all tempo mapping and time signature - information should be manipulated in the Timebase Master--Non will - respond to these changes automatically. If there is no Timebase - Master registered when Non starts, it will take over that role - instead. This is useful if you simply plan to use Non as a musical - instrument. - -: Control - - Non creates two MIDI input ports, one for /performance/ data and one - for /control/ data. The control port is used to control Non with - hardware MIDI controllers, such as the BCF2000, or other software. - The performance port is used to record musical data into patterns. - -: Playback - - The playback mode can be toggled between Pattern, Sequence and - Trigger. In Pattern mode (the default), all patterns are played - simultaneously, from the beginning, and looped forever. Since - patterns may differ widely in length, interesting compositions are - possible. In this mode, Non makes for a very intuitive software - instrument--rivaled only by the excellent program FreeWheeling (a - live audio looper.) - - In Sequence mode, playback strictly follows the sequence list and - the Jack transport, and does not loop. This mode is suitable for - parallel compositions between Non and a Jack Timebase Master capable - DAW. - - Trigger mode is very much like Pattern mode, except that all - patterns begin muted and must be enabled via the trigger view. - -: Sister Projects - - Much of the inspiration to move forward with Non was derived from JP - Mercury's highly useful and successful FreeWheeling - looper. Mr. Mercury is a visionary. - - But the closest sister of Non has to be the amazingly capable - ZynAddSubFX soft-synth by Nasca Octavian Paul. ZynAddSubFX, like - Non, utilizes the FLTK GUI toolkit, and has recently begun to - support Jack MIDI (albeit in a limited fashion.) This is, hands - down, the best synth available for Linux, and probably one of the - best period. If all you have is Non and Zyn, you have all that you - require to make great music. - - Of course, this section can hardly go without mention of Rob Buse's - Seq24. It was the author's unending frustration with the abysmal - performance and absurd limitations of Seq24 that, more than any - other single factor, inspired him to write Non. The most - frustrating aspect was that, prior to Non, Seq24 was, in the - author's opinion, the best sequencer available on Linux. Seq24, - which claims to be light and free of bloat is, without comparison, - the slowest, most poorly optimized sequencer the author has - tried. Even the huge, snarling beast that is RoseGarden out performs - Seq24 in every way but start time. - - Those days are over. diff --git a/sequencer/doc/Makefile b/sequencer/doc/Makefile deleted file mode 100644 index fcca551..0000000 --- a/sequencer/doc/Makefile +++ /dev/null @@ -1,21 +0,0 @@ - -SRCS=$(wildcard *.mu) -OBJS=$(SRCS:.mu=.html) - -%.html: %.mu - @ echo Mupping $<... - @ mup.wrapper html $< - -.PHONY: all clean - -all: $(OBJS) - -upload: all - @ rsync -L mup.css MANUAL.html *.png ssh.tuxfamily.org:/home/non/non-sequencer.tuxfamily.org-web/htdocs - -install: - @ install -d "$(DESTDIR)$(DOCUMENT_PATH)/non-sequencer" - @ install -m 644 $(OBJS) *.png mup.css ../../COPYING "$(DESTDIR)$(DOCUMENT_PATH)/non-sequencer" - -clean: - rm -f $(OBJS) \ No newline at end of file diff --git a/sequencer/doc/icon.png b/sequencer/doc/icon.png deleted file mode 120000 index a9b677a..0000000 --- a/sequencer/doc/icon.png +++ /dev/null @@ -1 +0,0 @@ -../icons/hicolor/256x256/apps/non-sequencer.png \ No newline at end of file diff --git a/sequencer/doc/mup.css b/sequencer/doc/mup.css deleted file mode 100644 index 10aceae..0000000 --- a/sequencer/doc/mup.css +++ /dev/null @@ -1,461 +0,0 @@ - -/* Example CSS Style for MUP */ - -body -{ - font: normal normal 14pt "Helvetica", sans-serif; -/* background: url("http://non.tuxfamily.org/background-pattern.png") fixed; */ - background-color: #121212; color: lightgray; padding: 0; margin: 0; -} - -a:link { - color: white; -} -a:visited { - color: olive; -} -a:active { - color: white; -} -a:link:hover { - text-decoration: underline; -} - -/* #(url) */ -a.ext:link { - color: red; - text-decoration: none; - border-bottom: dashed silver 1; -} -a.ext:visited { - color: darkred; - border-bottom: dashed silver 1; - text-decoration: none; -} - -/* #(ref) */ -a.int:link { - border-bottom: dashed silver 0.15em; -} -a.int:link:hover { - text-decoration: none; - color: white; -} - -/* - a[href^="#"]:link { - border-bottom: dashed silver 0.15em; - } - a[href^="#"]:link:hover { - text-decoration: none; - color: white; - } - */ - -p:contains("Warning:") { - background: #d00; - color: white; - border: dotted gray 0.5em; - display: block; -} - -/* First letter of first paragraph of every chapter */ -/* - h1 + p:first-letter { - text-transform: uppercase; - float: left; - line-height: 0.8em; - font-size: 350%; - font-family: Serif; - letter-spacing: 0; - margin-right: 0.1em; - margin-top: 0.1em; - border: solid gray 1px; - padding: 1px; - color: #d00; - text-shadow: #666 3px 3px 3px; - } - */ -/* First paragraph of every chapter */ -/* - h1 + p { - text-indent: 0; - } - */ - -/* cover */ -#cover * { - background: transparent; -} -#cover { - position: relative; -/* background: #da0;*/ - background: #555; - color: #aaa; - text-align: center; - margin: 0; - padding: 0.5em; - border-top: 4px solid black; - border-bottom: 4px solid black; -} -#cover h1, #cover h3 { - text-shadow: #222 0.2em 0.2em 0.2em; - color: white; - border: none; - letter-spacing: 0.2em; - line-height: 0.8em; - margin-left: 2em; - margin-right: 2em; -} -#cover h1:before, #cover h1:after { -/* content: "::"; */ - font-size: 300%; - color: black; -} -#cover h1:before { - position: absolute; - top: 0.2em; - left: 0.1em; -} -#cover h1:after { - position: absolute; - top: 0.2em; - right: 0.1em; -} -#cover hr { - display: none; -} - -hr:first-child { - display: none; -} - -hr { - height: 0.2em; - background: #555; - color: #555; - margin-left: 0.5em; -} - -#cover a:visited { - color: black; -} - -/* endnote */ -#endnote { - color: black; -} - -/* TOC */ -#toc { - position: relative; -} -#toc hr { -} -#toc h1 { -} -#toc ul { - font-size: 125%; - font-weight: bold; - margin-bottom: 1em; -} -#toc ul ul { - font-size: 90%; - font-weight: normal; - margin-bottom: 0; -} -#toc li { - list-style: none; - -} -#toc a:link { - border-bottom: 0; -} - -/* */ -#body { - position: relative; - margin: 0 auto; - padding: 0.5em; - max-width: 900px; - background-color: #1c1c1c; -} -/* ;, : */ -h1 { - color: #fff; - border-bottom: solid #444 0.1em; - text-shadow: 1px 1px 2px #000; - -} -/* ::, :::, ::::, :::::, :::::: */ -h2, h3, h4, h5, h6 { - color: #fff; - text-shadow: 1px 1px 2px #000; - -} - -/* tables, figures */ -.fig caption { - color: gray; - text-align: center; - /* Required for Mozilla */ - margin: auto; -} -.fig table { - border: none; - margin: auto; -/* border-collapse: collapse; */ -} -/* / */ -.fig.table th { - border: none; - background: gray; - color: black; -} -/* [ */ -.fig.table td { - border: none; - background: silver; - color: black; - padding-left: 1em; - padding-right: 1em; - padding-top: 0.2em; - padding-bottom: 0.2em; -} -/* < */ - -.fig.image table { - border: none; - background: transparent; - max-width: 100%; -} -.fig.image tr, .fig.image td { - border: none; - background: transparent; - padding: 0; -} - -.fig.image img -{ - max-width: 900px; -} - -/* */ -p { - margin-right: 2%; - text-align: justify; - text-indent: 1em; -} -/* > */ -.example * -{ - background: transparent; -} -.example table -{ - margin: 0; - padding: 0; - table-layout: fixed; - width: 100%; - caption-side: top; - overflow: auto; -} -.example caption -{ - caption-side: top; - -} -.example { -} -.example p { - display: inline; - margin: 0; - padding: 0; - text-align: center; -} -.example pre { - margin-top: 0; - font-family: Monospace; - padding: 1em; - border: solid 1px black; - background: #222; - color: white; - display: block; - overflow: auto; - /* Every browser should support border radii */ -/* -moz-border-radius: 0.5em; - border-radius: 0.5em; */ -} -/* " */ -/* - .quote:before { - float: left; - font-size: 500%; - content: "\201C"; - } - */ -/* - blockquote:after { - content: "\201D"; - }*/ -.quote blockquote { - padding: 0.5em; - margin-left: 0.5em; - font-family: Serif; - border-left: solid 0.4em gray; - /* background: #333; */ - color: white; -} -/* ^ */ -small { -/* - color: silver; - font-size: 50%; - */ -} -.footnote p { - color: silver; - margin: 0; -} - -/* Popup footnotes */ -.footnote p { - display: none; -} -.footnote p:target { - display: block; - overflow: auto; - position: fixed; - left: auto; - bottom: 0; - right: 0; - max-width: 50%; - border: solid 0.3em white; - -moz-border-radius: 0.5em; - background: black; - padding: 0.2em; -} - -/* { */ -.admonition * { - background: transparent; - color: white; -} -.admonition dl -{ - display: table; - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition dt -{ - display: table-cell; - vertical-align: center; - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} -.admonition dd -{ - padding-left: 0.4em; - display: table-cell; - width: 100%; - text-align: justify; -} - -.admonition table -{ - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition td { - width: 100%; - text-align: justify; -} -.admonition td:first-child:contains("Warning:") { - background: #900; -} -.admonition td:first-child:contains("Caution:") { - background: #960; -} -.admonition td:first-child:contains("Note:") { - background: #690; -} -.admonition td:first-child { - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} - - -/* #(b) */ -/* b { color: olive; } */ -/* #(c) */ -tt { - color: #7f0; -} -/* ! keywords ... */ -p em { - color: gray; - font-style: normal; - font-weight: bold; -} - -/* *, + */ -/* Bullet, numbe */ -li { - color: #f0f; -} -/* Text */ -li span, li p { - color: white; -} -li p { - color: red; - display: block; -} -ul { - list-style-type: square; -} -dl { - margin-left: 2%; - margin-top: 1em; -} -/* = */ -dt { - background: #181818; - padding: 0.2em; - font-variant: small-caps; - font-weight: bold; - color: #f0f; -} -dd { - color: white; - text-align: justify; - margin-right: 5%; -} -dt a:link, dt a:visited { - color: #f0f; -} -dt a:link:hover { - color: silver; - text-decoration: underline; -} diff --git a/sequencer/doc/non-cursors.png b/sequencer/doc/non-cursors.png deleted file mode 100644 index ca3cd7f..0000000 Binary files a/sequencer/doc/non-cursors.png and /dev/null differ diff --git a/sequencer/doc/non-event-editor-notes.png b/sequencer/doc/non-event-editor-notes.png deleted file mode 100644 index 6318641..0000000 Binary files a/sequencer/doc/non-event-editor-notes.png and /dev/null differ diff --git a/sequencer/doc/non-new-about.png b/sequencer/doc/non-new-about.png deleted file mode 100644 index 543e430..0000000 Binary files a/sequencer/doc/non-new-about.png and /dev/null differ diff --git a/sequencer/doc/non-patchage.png b/sequencer/doc/non-patchage.png deleted file mode 100644 index 3379098..0000000 Binary files a/sequencer/doc/non-patchage.png and /dev/null differ diff --git a/sequencer/doc/non-pattern-editor.png b/sequencer/doc/non-pattern-editor.png deleted file mode 100644 index e56e2e5..0000000 Binary files a/sequencer/doc/non-pattern-editor.png and /dev/null differ diff --git a/sequencer/doc/non-pattern-triggers.png b/sequencer/doc/non-pattern-triggers.png deleted file mode 100644 index b852378..0000000 Binary files a/sequencer/doc/non-pattern-triggers.png and /dev/null differ diff --git a/sequencer/doc/non-phrase-editor.png b/sequencer/doc/non-phrase-editor.png deleted file mode 100644 index eda1218..0000000 Binary files a/sequencer/doc/non-phrase-editor.png and /dev/null differ diff --git a/sequencer/icons/hicolor/128x128/apps/non-sequencer.png b/sequencer/icons/hicolor/128x128/apps/non-sequencer.png deleted file mode 100644 index b228107..0000000 Binary files a/sequencer/icons/hicolor/128x128/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/16x16/apps/non-sequencer.png b/sequencer/icons/hicolor/16x16/apps/non-sequencer.png deleted file mode 100644 index aaf17b2..0000000 Binary files a/sequencer/icons/hicolor/16x16/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/192x192/apps/non-sequencer.png b/sequencer/icons/hicolor/192x192/apps/non-sequencer.png deleted file mode 100644 index 62d92fa..0000000 Binary files a/sequencer/icons/hicolor/192x192/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/256x256/apps/non-sequencer.png b/sequencer/icons/hicolor/256x256/apps/non-sequencer.png deleted file mode 100644 index fc4e65f..0000000 Binary files a/sequencer/icons/hicolor/256x256/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/32x32/apps/non-sequencer.png b/sequencer/icons/hicolor/32x32/apps/non-sequencer.png deleted file mode 100644 index 407f604..0000000 Binary files a/sequencer/icons/hicolor/32x32/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/36x36/apps/non-sequencer.png b/sequencer/icons/hicolor/36x36/apps/non-sequencer.png deleted file mode 100644 index 03da8b1..0000000 Binary files a/sequencer/icons/hicolor/36x36/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/48x48/apps/non-sequencer.png b/sequencer/icons/hicolor/48x48/apps/non-sequencer.png deleted file mode 100644 index f470035..0000000 Binary files a/sequencer/icons/hicolor/48x48/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/512x512/apps/non-sequencer.png b/sequencer/icons/hicolor/512x512/apps/non-sequencer.png deleted file mode 100644 index 0555edc..0000000 Binary files a/sequencer/icons/hicolor/512x512/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/64x64/apps/non-sequencer.png b/sequencer/icons/hicolor/64x64/apps/non-sequencer.png deleted file mode 100644 index d36acd4..0000000 Binary files a/sequencer/icons/hicolor/64x64/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/72x72/apps/non-sequencer.png b/sequencer/icons/hicolor/72x72/apps/non-sequencer.png deleted file mode 100644 index 8d8c26b..0000000 Binary files a/sequencer/icons/hicolor/72x72/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/96x96/apps/non-sequencer.png b/sequencer/icons/hicolor/96x96/apps/non-sequencer.png deleted file mode 100644 index 12c4295..0000000 Binary files a/sequencer/icons/hicolor/96x96/apps/non-sequencer.png and /dev/null differ diff --git a/sequencer/icons/hicolor/scalable/apps/non-sequencer.svg b/sequencer/icons/hicolor/scalable/apps/non-sequencer.svg deleted file mode 100644 index 1cc5023..0000000 --- a/sequencer/icons/hicolor/scalable/apps/non-sequencer.svg +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sequencer/icons/icon-16x16.xpm b/sequencer/icons/icon-16x16.xpm deleted file mode 100644 index f6b1d30..0000000 --- a/sequencer/icons/icon-16x16.xpm +++ /dev/null @@ -1,774 +0,0 @@ -/* XPM */ -static char *icon_16x16[] = { -/* columns rows colors chars-per-pixel */ -"512 512 256 2 ", -" c #000101A00002", -". c #067A08890687", -"X c #020207070808", -"o c #048C0AD60B14", -"O c #09F70C1F0A1D", -"+ c #0CBA105B0EB4", -"@ c #04510E53104C", -"# c #067714141600", -"$ c #099E155315FF", -"% c #057F15521849", -"& c #085E18D91AB0", -"* c #0A061A811C4F", -"= c #12C014D012C0", -"- c #16AE190B1704", -"; c #13E91B9C199A", -": c #1ACC1D091B07", -"> c #1EC520C71EC5", -", c #066F1E28212B", -"< c #0C031E15202E", -"1 c #0707212124E5", -"2 c #0B8C211923F4", -"3 c #0BBA26322A1E", -"4 c #0C6228BB2CB3", -"5 c #12E622F6238D", -"6 c #1A4B278A2745", -"7 c #118B29952CC1", -"8 c #0CED2DBE324D", -"9 c #13A62D2D310C", -"0 c #0CDA33663939", -"q c #0ED036EE3CE9", -"w c #15F834B538FD", -"e c #1A6039BA3DF8", -"r c #21A923D121CF", -"t c #245F29512776", -"y c #2B8A2D8C2B8A", -"u c #2E2F303D2E37", -"i c #281D3658352A", -"p c #325534C2329C", -"a c #373239343732", -"s c #38FD3C3C3AFF", -"d c #3F2E40463F3F", -"f c #0E303C6F43AA", -"g c #10E43C00429D", -"h c #1DAA3E3E424B", -"j c #2D2D3F3F4040", -"k c #0E9A44734C35", -"l c #169244B74B0D", -"z c #139D4C245419", -"x c #1A994BE052E3", -"c c #161654215CF6", -"v c #1C7256375E6A", -"b c #24F643144617", -"n c #358B40CF4040", -"m c #24CB4D9452BC", -"M c #23DC505A5660", -"N c #223756735DE5", -"B c #272757575DC4", -"V c #385851715353", -"C c #188A5BB16565", -"Z c #293E5C8563DE", -"A c #19DA62426CAC", -"S c #1A91675372AD", -"D c #1B7869927556", -"F c #171770707D7D", -"G c #1CA470E97D7D", -"H c #277362AE6A4C", -"J c #39C8648168A1", -"K c #240D6D3E7748", -"L c #2AA86D0C75ED", -"P c #33B46E187575", -"I c #23B372157CAF", -"U c #2BE772DF7C54", -"Y c #332B740A7C8B", -"T c #388E75757D7D", -"R c #443A453B443A", -"E c #45784A174916", -"W c #4C234D314C2B", -"Q c #4F4F50504F4F", -"! c #46F853B65252", -"~ c #542255335427", -"^ c #5701590357D8", -"/ c #5B655C665B65", -"( c #5F5F60605F5F", -") c #469C620C6363", -"_ c #5667640E6363", -"` c #4B0B71717474", -"' c #588372C8741E", -"] c #61AA62AB61AA", -"[ c #676768686767", -"{ c #6B786C796B78", -"} c #6F6F70706F6F", -"| c #68BE75757373", -" . c #732D742E732D", -".. c #7A6E7B6F7A6E", -"X. c #7F7F80807F7F", -"o. c #1CBB7B0D8888", -"O. c #2424764F818E", -"+. c #2B5E7AD78615", -"@. c #23C17F268C3D", -"#. c #341D7ADD8472", -"$. c #4D4D7F7F8484", -"%. c #1E51872096C9", -"&. c #236381418E8E", -"*. c #2C0D80908C9C", -"=. c #3333819E8CA2", -"-. c #3B7582DF8CAF", -";. c #29AA899B9690", -":. c #38BF8A419527", -">. c #347D91919E30", -",. c #24C293E6A493", -"<. c #2C129548A3E3", -"1. c #265D9C77AD9B", -"2. c #2B739DDBAE47", -"3. c #32CA95CEA399", -"4. c #3C569775A39A", -"5. c #32439EE3AE9D", -"6. c #3B3B9B9BA8A8", -"7. c #27279F9FB0B0", -"8. c #3939A136AFAF", -"9. c #2A9AA282B383", -"0. c #271EAB98BEA6", -"q. c #2BE5A9C6BBD8", -"w. c #3558A4F6B491", -"e. c #3369AB67BC42", -"r. c #3C26AB5DBADC", -"t. c #58FD8315863D", -"y. c #4E138E2B95BD", -"u. c #4415937C9E12", -"i. c #787885DB8484", -"p. c #70108C2C8C8C", -"a. c #68E8947A97FE", -"s. c #42CF978AA309", -"d. c #45179C77A83A", -"f. c #43E9A20BAF45", -"g. c #4BBFA396AF3B", -"h. c #4885A9CBB73D", -"j. c #4316ACACBB8E", -"k. c #52BCAD07B940", -"l. c #457EB1B1BFBF", -"z. c #4C00B248BF64", -"x. c #538AB2FBBF88", -"c. c #7558A617A937", -"v. c #7090ADADB353", -"b. c #2D19B4DCC83E", -"n. c #296AB4D6C8EA", -"m. c #29C3B481C8FB", -"M. c #3535B66FC8C8", -"N. c #3956BF86D2D2", -"B. c #4808B80DC71C", -"V. c #5731BB5CC872", -"C. c #79FABAFAC282", -"Z. c #2DB5C469DA9E", -"A. c #34B5C2C2D7E7", -"S. c #3CE0C242D4C8", -"D. c #33D8C5D7DB48", -"F. c #3C17C771DAF2", -"G. c #02B4DAEEFB35", -"H. c #0B80DC21FAFA", -"J. c #1394DD43FAFA", -"K. c #1BA7DE3AFAFA", -"L. c #2ED9CF24E602", -"P. c #351ECD70E328", -"I. c #36C5D4E2EB6B", -"U. c #23A4DF5FFAFA", -"Y. c #2929DFDFFAFA", -"T. c #369BDD32F559", -"R. c #2D4BE0E0FAFA", -"E. c #3F3FE0E0F7F7", -"W. c #32D4E142FAFA", -"Q. c #3BD0E297FAF9", -"!. c #5C5CC250CF79", -"~. c #43C7C230D3C5", -"^. c #4BA1C3AED405", -"/. c #4855C890DAD1", -"(. c #53DAC58FD533", -"). c #5BD7C663D516", -"_. c #581ECC26DBFC", -"`. c #61FFCC1ADA77", -"'. c #7373CA30D507", -"]. c #4862D6BCEA1C", -"[. c #4C0CD696E9E9", -"{. c #59FAD827E918", -"}. c #65ECD76BE66C", -"|. c #477AE147F65C", -" X c #43DAE3C9F9F9", -".X c #4BDEE4CDF9F9", -"XX c #5970E36EF63B", -"oX c #53EBE5FCF9F9", -"OX c #5C19E714F9F9", -"+X c #6B6BE0E0EFEF", -"@X c #68BEE445F4AB", -"#X c #62D7E7E7F9F8", -"$X c #66B7E8E8F9F9", -"%X c #6BF1E93FF9F9", -"&X c #7171E6E6F6F6", -"*X c #7444EA54F9F9", -"=X c #7BE2EB6BF9F9", -"-X c #849085918490", -";X c #8B198C1A8B19", -":X c #8F8F90908F8F", -">X c #888896969494", -",X c #94A495A594A4", -" + t p u u p u u u u u u u p u u u u u u u u p u u u u u u > > + X X = r r u u u u u u u u u u u u u u u u p u u u u u u u u u u u - > > X O t u u u u u u u u u u u p u u u u u u p u u p u u u u p r > = X X + > > u u u p u u u u u u u u u p u u u u u u u u u p u u u u : X > > . X . r u u u u u u u u p u u u u u u u u u u u u p u u u u u r > = X X X X X X ", -" X X X X . E X.8XCXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXKXJXJXJXJXJXKXJXCX} . . .VXJXJXVX{ X = . - r ~ ,XCXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXE R JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX:XQ r = r Q ;XCXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX( X X X X X X X ", -"X X X X X . NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX,X+ X X r 5XKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX1X 0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX4X; X X X X ; X X = ;XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmX X X X X X X ", -" X X X X X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX . X X X ;XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX> p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX;X X ..JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp r JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX CXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX6X 1XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X X + CXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXmX X X X X X X ", -" X X X X : KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX5X X X X X X 8XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX O JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX9X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX{ X X X > JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X ", -" X X X X / JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy R JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X X X r JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX/ X + JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX/ X X X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW . a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXQ a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X ; JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -"X X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X X X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd - KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXQ a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X Q KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X ; JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXy X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X X X u KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXd X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -"X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X X . JXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa . W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X . . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X Q JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X X ", -" X X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp W KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X X ; JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X ", -" X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW . X p KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X X X - KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXQ a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] . X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X X X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X . - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X ; KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X X d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXu X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa Q JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs Q JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXQ a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X X ", -"X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs X Q JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs X W KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW . X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X X X X X ", -" X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X ; JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW . d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa Q KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXW X X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJX^ X X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXu X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXR X - KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -"X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa Q KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X : KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] . X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXy X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd . W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXQ s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa Q KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[ X X ", -" X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X ; JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd X : JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW . d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X JXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X X X [ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW p KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X X ", -" X X X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X ", -" X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa Q KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX~ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X X X ", -" X X X X X ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXy X X X u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X . - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X ", -" X X X X / JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXt X X X t JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu E JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXE X X X X > JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXE p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXQ X X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX/ X X X X ", -" X X X X X W JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX= X X - JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXr d JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXd > JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd VXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X X X X ", -" X X X X X s JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX. X X . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKX= a JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX . X X ~ JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXp + JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXu X X X X 0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXd X X X X X X X X X ", -" X X X X r JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVX X X X VXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXCX = JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKX6X X X . :XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX= JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX- X 6XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX> X X X X ", -" X X X X X VXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX1X X X X 4XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX6X X CXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXr X X = CXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVX 6XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmX X X X X X X .JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX X X ", -" X X X X X JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX... } JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX- 9XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX. X X -XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXCXO X X X X X X X ", -" X X ..JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXW X X X R JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX^ 4XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmX~ = X - ( 0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKX JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXX. X X X X X X ", -" X X X X X X X X - CXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmX. X X . 0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNXO u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX9X1XX.t - } X ", -" X X X ^ KXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXCXu X X y JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXs X ;XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX( u VXJXJXJXJXNXu ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX-X X p JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKX^ X X X = VXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX] X X X X ", -" X X X X 4XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXX. X X X X .JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX-X X O mXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXa O mXJXJXJXJXJXKXNX+ u JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmXO X X.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX1X X E JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX6X X X X X X X X X ", -" X X X X X X X > NXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX8XO X X X . 6XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX0XO X > NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX6X E JXJXJXJXJXJXJXJX[ -XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX> O 0XKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX: X X X X X ;XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXVX> X X X X X X ", -" X X X u VXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmX= X X X + mXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX: t NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXVX { JXJXJXJXJXJXJXJX,X 8XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmXr = mXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVXt X X . 5XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVXa X X ", -" X X X X X X y NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX8X= X X X X - 9XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKX0X; X - 8XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVX X | JXJXJXJXJXJXJXJX:X 8XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX4X= X X - 0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmXr X X X X . ;XCXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXVXr X 0XJXJXJXJXJXJX8XX r CXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXVX .= X p 5XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX0Xd X X X : ;XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXmXW X X X ", -" X X X X X X p X.mXJXJXJXJXJXJXJXJXJXCX6X| r X X X X : } 8XJXJXJXJXKXJXJXJXJXCX8X..y X X X = [ 6XCXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXmXp : 8XJXJXJXJX4X+ d VXJXJXJXKXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXVX1X] O X X > .8XJXJXJXJXJXJXJXJXJXJX8XX.u X X X X X = ] 6XCXJXJXJXJXJXJXJXJXJX0X-Xs X X X X X X X ", -" X X X X X X X X = a ~ ] [ { ( R r . X X X X X + u Q ] { { ( Q y . X X . u R / { { { { } { { { } { { { { { { { { { } { { { { { { } { { [ R . p [ ] y O R { { { [ { { { { { { } { { { { { { { { } { { { { { { { { { ^ E u X X X + a W ( { { ( Q y . X X X O y R / { { [ ~ u + X X X X X X X ", -" X X X X . X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -"! X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X W ", -"UXNX~ . X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ^ BXUX", -"UXUXUXmXW X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X E mXUXUXUX", -"UXUXUXUXUXqXd X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X R mXUXUXUXUXUX", -"UXUXUXUXUXUXUX9Xp X X X X X X X X X X X X X X X X X X X X X X X X a 9XUXUXUXUXUXUXUX", -"UXUXUXUXUXUXUXUXUX9Xu X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X u 9XUXUXUXUXUXUXUXUXUX", -"UXUXUXUXIXUXUXUXUXIXIX4Xt X X X X X X X X X X X X X X X X X X X X X X X X X X X t 2XUXUXUXUXUXUXIXIXUXUXUX", -"UXUXUXIXUXUXUXIXIXUXUXUXUX5Xr X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X r 2XUXUXUXIXUXUXIXIXUXUXIXUXUX", -"UXIXIXUXIXIXUXIXUXIXIXUXIXUXLX,X> X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X - ,XIXUXIXUXIXUXIXIXUXIXUXIXIXUXIX", -"IXUXIXIXUXIXUXIXIXIXUXIXIXIXUXUXIX>X- X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ; ,XLXIXUXIXUXIXUXIXUXUXIXUXIXIXUXIXUX", -"IXUXUXIXUXIXIXIXIXUXIXIXIXUXIXIXUXUXKXi.= X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X + i.KXUXIXUXIXUXIXIXIXIXIXIXIXUXIXUXIXIXUX", -"IXIXIXIXIXIXUXIXIXUXIXUXIXIXIXIXIXIXIXIXKXi.= X X X X X X X X X X X X X X X X X X X X X = i.KXUXUXIXIXIXIXIXIXIXUXIXUXUXIXIXIXIXIXIXIX", -"IXUXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXCX| O X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X O .AXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXUXIXIXIX", -"IXIXIXIXIXPXIXIXIXIXIXIXPXIXIXIXIXIXIXIXIXIXIXIXAX| O X X X X X X X X X X X X X X X X X X X X O | AXUXIXIXIXIXIXIXIXIXIXIXPXIXIXPXIXIXIXPXIXPXIXIXIX", -"IXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXPXIXIXIXIXIXIXIXUXIXBX_ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X . _ BXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIX", -"IXPXIXPXIXIXPXIXIXPXIXPXIXIXPXIXIXIXIXPXIXIXIXIXIXIXIXIXBX/ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ] BXIXPXIXIXPXIXIXIXPXIXIXPXIXPXIXIXPXIXIXIXIXPXIXIXIXPXIXIX", -"PXIXIXPXIXPXPXIXPXIXIXPXIXIXPXIXPXIXPXIXPXIXIXPXPXIXPXIXIXIXMX! X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X . ~ MXIXIXPXIXIXPXIXPXPXIXIXPXIXIXIXIXIXPXPXIXIXPXPXIXPXIXPXPXIXIX", -"IXPXIXPXPXIXIXPXIXPXPXIXPXPXIXPXPXIXIXPXIXPXPXIXIXPXIXPXIXPXIXIXqXE X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X E qXIXPXPXIXIXPXIXPXPXIXIXPXPXIXPXIXPXPXPXIXIXPXPXIXIXPXIXIXIXPXIXPX", -"PXPXIXIXIXIXPXIXPXPXIXIXIXIXIXIXIXPXPXIXPXIXIXPXPXIXPXIXPXIXPXPXPXIXqXd X X X X X X X X X X X X X X X X X X X X X X X X X n qXIXPXPXIXPXPXPXPXIXIXPXPXPXIXPXIXPXPXPXIXIXPXPXIXIXPXPXIXIXPXPXIXPXPX", -"PXIXPXPXPXPXIXPXPXIXPXPXPXPXPXPXPXIXPXPXIXPXPXIXPXPXPXIXPXPXPXIXIXPXPXIX7Xp X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X p 7XIXPXPXIXIXPXPXIXPXIXPXPXPXIXIXPXIXPXPXIXPXPXIXPXIXPXPXIXPXPXPXPXIXPXPXIX", -"PXPXIXPXPXIXPXPXPXIXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPX7Xp X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X u 7XPXIXPXPXPXPXPXPXIXPXIXPXPXPXPXIXPXPXPXPXPXPXIXPXPXPXPXPXPXIXPXPXPXPXPXIXPXPX", -"PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXIXPXPXIXPXPXPXPXPXPXPXPXIXPXPXPXPX2Xt X X X X X X X X X X X X X X X X X X X X X X X X X t 2XPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPX", -"PXPXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXIXPXIXPXPXIXPXPXPXPXPXPXIXPXPXPXPXIXPXPXPX2Xr X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X r 2XPXIXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXPXPXPXIX", -"PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXHXPXPXPXHXPXPXPXPXPXPXPXPXPXPXPXHXPXPXHXIXHX>X> X X X X X X X X X X X X X X X X X X X X X X X X X > >XHXPXPXHXPXPXPXPXPXPXPXPXPXIXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXIXPXPXPXHX", -"IXPXPXPXPXHXPXPXPXPXHXPXPXPXPXPXPXPXPXPXPXPXPXHXPXPXPXPXPXPXPXPXPXHXPXPXPXPXPXPXPXPXPXHXPXKX>X; X X X X X X X X X X X X X X X X X X X X X X X ; >XKXPXPXPXPXPXPXHXPXPXPXPXHXPXPXPXPXPXPXHXPXPXPXPXHXPXPXPXPXPXPXPXPXPXPXHXPXPXPXPXPXPXPXPXPXPX", -"HXPXPXHXPXPXPXHXPXPXHXPXHXPXHXPXPXHXHXPXPXHXPXPXHXHXPXHXPXHXPXHXPXPXPXHXPXHXPXHXPXHXPXPXPXHXPXAXi.= X X X X X X X X X X X X X X X X X X X X X X X X X X = i.AXPXHXHXPXHXPXHXPXPXPXHXPXHXPXPXHXPXPXHXPXPXPXHXPXPXHXPXPXHXHXPXHXPXPXHXPXPXHXPXHXPXHXHXPXHXPXHX", -"PXPXHXPXPXHXPXPXHXPXPXPXPXPXHXPXHXPXPXPXPXPXPXHXPXPXPXPXPXHXPXHXPXHXPXPXHXPXPXPXPXPXPXHXHXPXPXPXPXAXi.= X X X X X X X X X X X X X X X X X X X X X X X X X + i.AXPXPXPXPXPXPXHXPXHXPXHXPXPXHXPXHXPXPXPXHXPXPXHXPXPXHXPXPXPXPXPXPXHXPXPXHXPXHXPXHXPXPXPXPXPXPXPXHXPX", -"HXHXPXHXPXHXHXHXPXHXPXHXHXPXHXPXPXHXHXHXHXHXHXPXPXHXHXPXHXPXHXPXPXHXHXHXPXHXHXPXHXHXHXPXPXHXHXHXPXHXPXZX| O X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X O | AXPXHXPXPXHXHXPXHXPXHXPXPXHXHXHXPXHXPXPXHXHXPXHXPXHXHXHXPXPXHXHXHXPXHXPXHXPXPXHXPXHXPXHXHXHXHXPXHXHXPXHX", -"HXPXPXHXHXHXHXPXPXHXHXHXHXPXPXHXHXPXHXPXHXPXHXHXHXHXHXHXPXHXPXHXPXHXPXHXPXHXHXHXPXHXPXHXPXHXPXHXHXHXPXHXHXZX| . X X X X X X X X X X X X X X X X X X X X X X X X X X O | ZXPXHXHXPXHXHXHXPXHXHXPXHXPXHXPXHXHXHXHXPXHXHXPXPXHXHXPXHXPXPXHXHXHXHXPXPXHXHXPXHXPXPXHXHXPXPXHXHXHXPXHXPXHX", -"HXHXHXHXHXPXHXHXHXHXHXPXHXHXHXHXHXHXHXHXHXHXHXHXHXHXPXHXHXHXHXHXHXHXHXHXHXHXPXHXHXHXHXHXHXHXHXHXPXHXHXHXHXHXPXBX_ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X _ BXHXHXHXPXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXPXHXHXHXHXHXHXHXHXHXHXHXHXHXHXPXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXBX_ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X _ BXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXMX! X X X X X X X X X X X X X X X X X X X X ! MXHXGXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXGXHXHXHXGXHXHXHXHXHXHXtXE X X X X X X X X X X X X X X X X X X X X ! tXPXHXHXHXHXHXHXHXHXHXGXHXGXHXHXHXHXFXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"GXHXHXHXGXHXHXHXHXHXHXFXFXHXHXHXHXHXFXHXHXHXFXHXHXFXHXHXHXHXHXHXGXHXGXGXGXHXGXGXGXGXGXGXGXHXGXHXGXGXHXHXGXHXHXGXGXHXGXHXGXHXHXtXn X X X X X X X X X X X X X X X X X X X X X X X X X X n tXHXGXHXHXHXGXHXHXGXGXHXGXHXHXHXHXGXHXHXHXHXFXHXHXHXHXHXFXHXHXHXGXHXHXHXGXHXHXHXHXHXHXFXFXHXHXHXGXHXHXHXHXHXHXFXFXHXHXHXHXHXFXHX", -"GXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXHXGXGXGXGXHXHXGXGXGXGXHXFXHXGXGXGXGXGXGXGXHXHXGXGXHXGXGXGXGXGXGXHXGXGXHXGXGXGXGXGXGXGXGXGXGXHX7Xi X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X i 7XHXHXGXHXGXGXGXHXGXGXGXGXGXGXHXGXGXHXHXHXHXFXFXHXGXGXGXGXGXHXGXGXGXGXGXGXGXGXGXGXGXHXGXGXGXHXGXGXGXGXGXGXGXGXGXGXGXHXGXGXGXHXGXHXGX", -"GXGXGXGXGXGXGXGXHXGXGXGXGXHXHXGXGXGXGXGXGXGXGXGXGXGXGXGXGXHXFXHXHXGXGXHXGXGXGXGXGXGXGXGXGXHXGXGXHXGXGXGXGXGXGXGXGXHXGXGXHXGXGXGXGXGXGX7Xi X X X X X X X X X X X X X X X X X X X X X X X X X X X i 7XGXGXGXGXGXGXGXGXGXGXGXGXGXHXGXGXGXGXGXHXFXHXFXHXHXHXHXGXGXGXHXGXGXGXGXHXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXHXGXGXGXGXGXGXGXGXGXGXGX", -"GXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXFX2Xt X X X X X X X X X X X X X X X X X X X X X t 2XFXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGX", -"GXGXGXGXGXGXFXGXGXGXGXGXGXFXGXGXGXGXGXGXGXFXFXGXGXGXFXGXGXGXGXGXFXGXGXGXGXGXGXFXGXGXGXFXGXGXGXFXGXGXGXGXGXFXGXGXFXGXGXGXFXGXGXGXGXGXGXFXGXGXFX2X6 X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 6 2XFXFXFXGXGXFXGXGXGXGXGXGXGXFXGXGXGXFXGXGXGXFXGXGXGXFXGXGXGXFXGXGXGXGXFXGXGXFXGXFXGXGXGXFXGXGXGXGXGXGXGXGXFXGXGXFXGXFXGXGXGXFXGXGXGXFXGXGXGXFXGX", -"GXGXFXGXFXGXGXFXFXGXFXFXGXFXFXGXGXGXGXFXFXFXGXGXFXGXGXFXGXFXFXGXGXGXFXGXGXFXFXGXFXFXGXGXFXGXGXFXGXGXFXGXGXGXFXGXGXGXFXGXGXGXGXGXFXGXGXFXFXGXGXFXFX>X; . X X X X X X X X X X X X X X X X X X X X X X X X X - >XFXFXGXGXGXFXFXGXGXFXGXGXFXFXGXGXGXFXGXGXGXFXGXFXGXFXGXGXGXFXGXFXGXFXGXGXGXFXGXFXGXGXGXFXFXGXFXFXGXGXFXFXGXGXFXGXGXFXGXGXFXFXGXGXFXFXGXGXGXFXGXGXFX", -"FXFXGXFXGXFXGXGXGXFXGXGXGXGXFXGXGXFXGXGXGXGXGXFXGXFXGXGXFXGXGXGXFXFXGXFXGXFXGXGXGXGXFXGXGXGXFXGXFXGXGXGXFXGXGXFXFXFXGXFXFXGXFXFXGXFXGXGXGXFXGXGXGXGXAXp.; X X X X X X X X X X X X X X X X X ; >XFXFXFXGXGXFXFXGXGXFXGXGXFXFXGXGXFXFXGXGXFXFXGXFXGXGXGXGXFXFXGXFXGXGXGXGXFXFXGXGXFXFXGXFXGXGXGXFXGXGXFXFXGXGXGXFXGXGXFXGXFXGXGXGXFXGXGXGXGXGXFXGXFXGXGX", -"GXFXFXFXGXFXFXGXGXFXGXGXFXGXFXGXFXGXFXGXGXFXFXGXFXGXHXFXFXFXGXFXGXFXFXGXFXGXGXFXFXGXGXFXFXFXGXFXFXGXFXFXFXGXGXFXGXFXHXFXFXHXFXGXFXGXGXFXGXFXGXFXFXGXGXFXAXp.+ X X X X X X X X X X X X X X X X = p.AXFXFXGXFXGXFXGXGXFXFXFXFXFXGXGXFXFXGXFXGXFXFXGXFXFXGXFXFXFXFXGXFXFXGXFXFXFXFXGXFXFXGXFXGXFXGXFXGXGXGXFXGXGXFXFXFXFXFXFXGXFXGXGXFXGXFXGXFXFXGXFXGXFXFXGXFX", -"FXFXFXFXGXFXFXGXFXFXFXFXFXFXFXFXGXFXFXFXFXFXGXFXFXFXFXFXHXFXFXFXFXFXGXFXFXFXFXGXFXFXFXGXFXGXFXFXFXGXFXGXFXFXFXGXFXFXFXFXFXFXGXFXFXFXFXFXGXFXFXGXFXFXFXGXFXFXZXi.+ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X = i.ZXFXGXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXGXFXFXFXFXGXGXFXFXGXFXGXFXGXGXFXGXFXFXGXFXGXGXGXFXFXFXGXGXFXFXFXFXFXFXFXFXGXGXFXFXFXFXFXFXFXFXFXGXFXFXGXFXFXFXGXFXGXGXFX", -"FXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXZX' O X X X X X X X X X X X X X X X X X X X X X X X X X X X . ' ZXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX", -"FXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXGXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXZX| O X X X X X X X X X X X X X X X X X X X X X X X X O | ZXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXGXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXGXFXFXFXFXFXGXFXFXFXFXFXFXGXFXFXFXFXFXFX", -"FXGXFXFXFXFXDXFXFXFXDXFXFXFXFXFXFXFXFXGXFXFXGXFXFXGXFXFXFXDXFXFXFXFXFXGXFXFXFXDXFXFXFXDXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXGXDXFXFXFXFXFXFXFXFXFXDXFXFXFXFXFXFXFXFXFXFXFXDXFXyX_ . X X X X X X X X X X X X X X X X X X X X X X X X X X X X X . ( yXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXDXFXFXFXFXFXFXDXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXDXFXFXFXFXGXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX", -"DXDXFXFXFXFXFXFXFXFXFXFXDXFXFXFXFXFXFXDXFXDXDXFXDXDXFXFXFXFXFXFXFXFXDXDXFXDXFXFXFXFXFXFXFXFXFXDXDXFXDXFXFXFXFXFXFXFXDXFXFXFXDXFXDXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXDXFXyX_ X X X X X X X X X X X X X X X X X X _ yXFXFXFXFXFXFXDXFXFXFXFXFXFXFXFXFXFXDXDXFXFXFXFXFXDXFXFXDXDXFXFXFXFXDXFXFXFXFXFXFXFXFXFXDXFXFXDXFXFXFXDXFXFXFXFXFXFXFXFXFXDXFXFXFXFXDXDXFXDXFXFXFXDXFXDXDXFXFXFXFXFXDXFXDXFXDX", -"FXFXDXFXDXFXFXDXFXFXFXFXDXFXDXFXFXDXDXFXFXFXFXFXFXFXDXFXDXFXFXDXFXDXFXFXFXDXFXFXFXFXDXDXFXFXFXDXDXFXFXDXDXDXFXFXFXDXFXDXFXDXFXFXFXFXDXFXDXFXFXDXFXDXFXFXDXFXDXFXFXFXDXFXFXFXFXFXyX! X X X X X X X X X X X X X X X X X X X X X ! yXFXFXDXFXDXFXFXDXDXFXDXFXDXFXFXFXFXDXFXFXFXFXFXDXFXFXFXFXDXFXFXFXFXDXFXFXFXFXDXDXFXFXFXFXDXFXDXFXFXFXDXFXFXFXFXFXDXFXFXFXDXFXFXFXFXDXFXFXFXFXFXDXDXFXFXFXFXFXDXFXFXFXDXFXFXDXFXFX", -"FXDXFXFXDXFXFXFXFXFXFXDXFXFXDXFXFXDXFXDXDXFXDXFXFXDXFXFXDXFXFXFXFXFXFXDXFXFXDXFXFXFXFXFXFXDXFXFXFXFXDXFXFXFXFXDXFXFXFXDXFXFXDXFXFXDXFXFXDXFXFXDXFXFXFXDXFXFXDXFXDXFXFXFXFXDXFXDXFXFXtX! X X X X X X X X X X X X X X X X X X X X ! tXFXFXDXFXFXFXFXDXDXFXFXFXFXFXFXFXDXFXFXFXFXDXDXFXFXFXFXDXDXFXFXFXFXDXFXFXDXDXDXFXFXFXFXDXDXFXFXFXDXFXDXFXFXFXFXDXDXFXFXFXDXFXFXFXDXFXFXFXFXDXDXFXFXFXFXFXDXFXFXDXFXFXDXFXFXFXFXFXFXDX", -"FXFXFXDXFXDXFXDXFXDXFXDXFXFXFXDXFXDXFXFXFXDXFXDXFXFXFXDXFXDXFXDXDXFXDXFXDXFXDXFXDXFXDXFXDXFXDXFXDXFXFXFXDXFXDXFXDXFXDXFXDXFXDXFXDXFXDXFXFXFXDXFXFXDXFXDXFXFXFXDXDXFXFXFXDXFXDXFXDXFXDXFXeXs X X X X X X X X X X X X X X X X n eXFXDXFXDXFXFXFXDXFXDXFXDXFXDXFXDXFXDXFXDXDXFXDXFXDXFXDXFXFXDXFXDXDXFXDXFXFXFXDXFXFXDXFXDXFXDXFXDXFXFXFXDXDXFXFXFXDXFXDXFXDXFXFXDXFXDXFXDXDXFXDXFXDXFXFXDXDXDXFXFXFXDXFXFXFXDXFXDXDXFXDXFX", -"DXDXDXFXDXFXDXFXDXFXDXFXDXDXDXFXDXFXDXFXDXFXDXFXDXDXDXFXDXFXDXFXDXFXDXDXFXDXFXDXFXDXFXFXDXFXDXDXFXDXDXDXFXDXFXFXDXFXDXDXFXDXFXDXFXDXFXDXDXFXDXFXDXFXDXFXDXDXDXFXFXDXDXDXFXDXFXDXFXDXFXDXDXFX7Xi X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X s eXDXFXDXFXDXFXDXDXDXFXDXFXDXFXFXDXDXFXDXFXDXFXFXDXFXDXFXDXFXDXDXFXDXFXFXDXFXDXDXFXDXFXDXFXDXFXDXFXDXFXDXDXFXDXFXDXDXDXFXDXFXDXFXDXFXDXDXFXDXFXFXDXFXDXFXDXDXFXDXFXDXDXFXDXDXDXDXFXDXFXFXDXFXDX", -"FXDXDXFXFXDXDXFXDXFXFXDXFXDXDXDXFXDXDXFXDXFXFXDXFXDXDXFXFXDXDXFXDXFXFXDXDXFXDXDXDXDXDXDXDXFXFXDXDXFXFXDXDXDXDXDXDXFXFXDXDXFXDXDXFXDXDXDXFXDXDXDXDXFXFXDXFXDXDXFXDXFXFXDXDXDXDXFXDXDXDXFXDXDXDXFX3Xy X X X X X X X X i 7XDXDXDXFXFXDXFXDXDXFXDXFXFXDXDXFXDXDXDXDXDXDXDXDXDXDXFXFXDXFXDXFXFXDXFXDXFXDXDXDXDXDXDXFXDXFXFXDXFXDXFXDXFXDXDXDXDXFXFXDXDXDXDXFXDXFXDXFXDXDXDXDXDXDXFXFXDXFXDXDXDXFXFXDXDXFXFXDXFXDXFXDXDXDXDXDX", -"DXDXDXDXDXDXDXFXDXDXDXDXDXDXDXFXDXDXFXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXFXDXFXDXFXDXFXDXDXDXDXDXFXDXDXFXDXDXFXDXDXDXDXDXFXDXFXDXDXFXDXFXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXFXDXDXFXDXFXDXDXFXDXDXDXDXDX3Xt X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 6 2XDXSXFXDXDXDXDXDXDXDXDXDXDXDXDXFXDXDXDXDXDXFXDXFXFXDXDXDXDXDXDXDXDXDXDXFXDXDXDXDXFXDXFXDXDXDXDXDXDXDXDXFXDXDXDXDXDXFXDXDXDXDXFXDXDXFXDXDXDXDXDXFXDXFXDXDXDXDXDXDXDXFXDXDXDXDXDXDXDXDXFXDXDXFXDXFXDXDX", -"DXDXDXDXDXFXDXDXDXDXDXFXDXDXDXDXDXDXDXDXDXFXDXDXDXDXFXFXDXDXFXDXFXDXDXDXDXDXDXFXDXDXDXDXDXFXDXDXFXDXDXDXDXDXDXFXDXDXDXDXDXFXDXDXDXDXDXDXDXDXFXDXDXDXDXFXDXDXDXDXDXDXDXDXDXFXDXDXFXDXFXDXDXDXDXDXDXDXDXDX2X> X X X X X X X X X X X X X X X X X X X X X > 2XSXDXDXDXDXDXFXDXDXFXDXDXFXFXDXDXDXDXFXDXDXDXDXDXDXDXDXDXFXDXDXDXDXDXDXDXDXDXFXDXDXDXDXDXFXDXDXFXDXDXFXDXDXDXDXDXDXFXDXDXDXDXDXDXDXDXDXDXDXFXDXDXFXDXDXDXDXDXDXDXDXFXDXDXDXFXDXDXDXDXDXDXDXFXDXDXFXDXDXDX", -"DXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXFXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXFXDXDXFXDXDXDXDXDXSXSXa.; X X X X X X X X X X X X X > a.SXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXFXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDX", -"DXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXFXAXp.; X X X X X X X X X X X X X X X X X X : p.DXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXAXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDX", -"DXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXSXDXDXDXDXDXSXDXDXDXDXDXDXSXDXDXDXSXDXDXDXDXSXDXDXDXDXDXDXSXSXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXSXZXp.+ X X X X X X X X X X X X X X X X X X X X X X X X X O p.ZXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXSXDXDXDXDXSXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXSXDXDXDXSXDXDXDXDXDXSXDXDXDXSXDXDXDXDXDXDXDXDXDXDXSXDXDXDXSXDXDXDXDXSXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDX", -"DXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXSXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXSXDXDXDXDXDXDXSXDXDXDXDXSXDXDXDXDXSXSXDXDXSXDXDXDXSXDXDXDXDXDXDXDXDXSXDXSXDXDXDXDXSXDXSXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXZXX.+ X X X X X X X X X X X X X X X X X X X @ p.ZXSXDXSXDXSXDXDXSXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXSXDXDXDXDXDXDXDXDXSXDXDXDXDXSXDXDXDXDXSXDXDXSXDXDXSXSXDXDXSXDXSXDXDXSXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDX", -"SXDXSXDXSXDXDXSXSXDXSXDXDXSXDXDXSXDXSXDXSXDXDXSXSXDXSXDXDXDXDXSXDXSXDXDXDXSXSXDXDXDXDXDXSXDXDXDXDXSXDXDXDXDXSXDXDXSXDXDXSXSXDXDXDXDXDXDXSXDXDXDXDXSXSXDXSXDXSXDXDXDXDXDXSXDXDXDXSXDXDXSXDXSXDXSXSXDXSXDXDXSXDXSXDXSXSXDXSXkX| . X X X X X X X X X X X X X X X X X X X X X X X O ' ZXDXSXSXDXDXDXDXDXSXDXDXDXDXSXDXDXSXDXSXDXSXDXSXSXDXDXSXDXDXDXDXDXDXSXDXSXDXSXDXDXDXSXDXDXSXDXDXDXSXDXDXSXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXSXDXSXDXDXDXSXDXDXDXSXDXDXSXDXDXDXDXDXSXDXSXDXDXDXDXDXSXSXDXDXSXDXDXSXDXSXDXDXSXDXSX", -"DXSXSXDXSXDXSXDXDXDXSXDXSXDXDXSXDXSXSXDXSXDXSXDXDXSXSXDXSXDXDXDXSXDXDXSXDXSXDXSXDXSXDXDXDXSXSXDXSXDXDXSXDXSXDXSXSXDXDXSXDXSXSXDXSXDXDXDXSXDXSXDXDXDXDXSXDXDXDXSXSXDXSXDXSXDXSXDXSXDXSXDXDXSXDXDXDXSXDXSXDXDXDXSXDXDXDXSXSXDXSXkX' O X X X X X X X X X X X X X + ' ZXSXDXDXDXDXDXDXSXDXDXDXSXDXSXDXSXDXSXDXSXDXDXDXSXDXSXDXSXDXDXDXSXDXSXDXSXDXSXDXSXDXSXDXSXDXSXDXSXSXDXDXSXDXSXDXSXDXDXDXSXDXSXDXDXSXDXSXSXDXSXDXDXDXDXSXDXSXDXSXDXDXSXDXDXSXDXDXDXDXDXSXDXSXDXSXSXDXSXDXDXDXDXDXDXSXDXSXDXDXDXSX", -"SXDXDXSXDXSXDXSXSXSXDXDXSXSXSXDXSXDXDXSXDXSXDXSXSXDXDXSXDXSXSXDXSXSXSXDXSXDXSXDXDXSXSXSXSXDXDXSXSXSXSXDXSXDXSXDXDXSXDXDXSXDXDXSXDXSXSXSXDXSXDXSXSXDXSXDXSXSXSXDXDXSXDXSXDXSXDXSXDXSXDXDXSXDXSXDXSXDXSXDXSXSXSXDXSXDXSXDXSXSXDXSXSXyX_ . X X X X X X X X X X X X X X X X X X X X X X X X X X X X _ iXDXSXSXSXSXSXSXSXSXDXSXSXDXSXDXSXSXDXSXDXSXDXSXSXDXDXSXDXSXDXSXSXSXSXDXSXSXDXSXDXSXDXSXDXSXDXSXDXSXSXDXSXDXDXSXDXSXDXSXSXSXDXDXSXSXSXDXSXDXSXDXDXSXSXSXSXDXSXDXSXDXSXSXDXSXSXDXSXSXSXSXSXDXSXDXSXDXDXSXDXSXSXSXSXSXSXDXDXSXSXSXDXSX", -"SXDXSXSXDXSXDXDXSXSXDXSXSXDXSXSXSXDXSXSXDXSXDXDXSXSXDXSXSXDXDXSXDXDXSXDXSXDXSXSXDXDXSXDXDXSXDXDXDXDXSXDXSXDXSXSXDXDXSXDXDXDXSXDXSXSXDXSXSXDXSXSXDXDXSXDXSXDXSXSXSXSXDXSXSXDXSXSXDXDXSXDXSXDXSXSXDXDXSXDXDXSXDXDXSXDXSXSXDXSXDXDXDXDXSXyX_ X X X X X X X X X X X X X X X _ yXSXDXSXSXDXSXDXDXSXSXDXSXDXSXDXSXDXSXDXSXDXSXSXDXSXDXSXDXSXSXDXDXSXSXDXDXSXSXDXSXSXDXSXDXSXSXDXSXSXSXDXSXDXSXDXDXSXSXDXSXDXSXDXSXSXDXSXDXSXDXDXDXSXSXDXDXSXDXSXSXDXDXSXSXDXDXSXDXDXSXDXDXSXDXDXSXDXDXSXSXDXDXSXSXDXDXSXDXSXDXSXDXDXSXDX", -"DXSXSXDXSXDXSXSXSXDXDXSXDXSXSXDXDXSXSXDXSXDXSXSXSXDXDXSXDXSXSXDXSXSXSXSXDXSXSXDXSXSXSXSXSXDXSXSXSXSXSXSXDXSXSXDXSXSXSXSXSXSXDXSXSXDXDXSXSXDXDXSXSXSXSXSXDXSXSXDXSXDXDXSXSXDXDXSXSXSXSXSXDXSXDXSXSXSXSXSXSXSXSXSXDXSXSXDXSXDXSXSXSXSXSXDXSXtX! X X X X X X X X X X X X X X X X X X X X X ! tXSXSXSXSXSXSXSXDXSXSXSXDXSXSXSXSXDXDXSXDXSXDXSXSXDXDXSXSXSXSXDXSXSXSXDXSXSXSXDXDXSXSXDXDXSXSXDXDXSXSXDXDXSXSXSXDXSXSXSXDXSXSXSXSXDXDXSXSXDXSXDXSXSXSXDXSXDXSXDXSXDXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXDXDXSXSXDXDXSXSXDXDXSXSXSXSXSXSXSX", -"SXDXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXDXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXDXSXDXSXSXSXSXDXSXSXSXSXSXSXSXSXDXSXDXSXSXSXSXDXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXDXDXSXSXSXSXDXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXDXSXDXSXSXSXDXSXSXSXSXSXSXSXSXSXDXSXSXSXtX! X X X X X X X X X X X X X ! tXSXSXSXSXSXSXDXSXDXSXSXSXSXSXSXSXDXSXSXDXSXSXSXSXSXSXSXSXSXSXDXSXSXDXSXSXSXSXSXSXSXDXSXDXSXSXSXSXSXSXSXSXSXDXSXSXDXSXSXSXSXSXSXSXDXSXSXSXDXSXSXSXSXSXSXSXDXSXSXSXDXSXSXSXDXSXSXSXDXSXSXSXDXSXSXSXDXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXDX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXDXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXwXn X X X X X X X X X X X X X X X X X X X X X n wXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXwXd X X X X X X X X X X X X X X X X X X X X X X X X j wXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX3Xt X X X X X X X X X X X X i 3XSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXnXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXnX3Xt X X X X X X X X X X X X X X X X X X X X X X X t 3XnXSXSXSXSXSXSXSXSXSXSXSXvXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXnXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXSXSXnXSXSXSXSXSXSXSXnXSXSXSX", -"SXSXSXSXSXSXnXSXSXnXSXnXSXnXSXnXSXSXSXSXnXSXnXSXSXnXSXnXSXnXSXSXSXSXnXSXSXnXSXnXSXSXnXSXnXSXnXSXSXSXnXSXSXnXSXnXSXSXnXSXnXSXnXSXSXnXSXnXSXSXSXSXSXSXnXSXSXnXSXnXSXnXSXSXSXSXSXSXSXSXnXSXSXvXSXSXnXSXnXSXnXSXnXSXSXSXSXSXnXSXnXSXnXSXnXSXnXSXSXnXSXSXSXSXnXSXSXSXnX3X6 X X X X X X X X X X X X ; 3XnXSXSXSXSXnXSXnXSXSXSXvXSXSXSXSXnXSXvXSXSXSXnXvXSXSXSXSXvXSXSXvXSXSXSXnXSXSXnXnXSXSXSXSXSXSXSXnXSXnXSXSXSXnXSXSXnXSXSXnXSXnXSXSXSXnXSXnXSXSXnXSXnXSXSXSXSXnXSXnXSXSXnXSXnXSXSXSXSXnXSXnXSXnXSXSXnXSXnXSXnXSXnXSXSXnXSXSXSXSXnXSXnXSXnXSXSXSXSXnXSXSXnXnXSXSXSXSXSX", -"SXnXSXSXnXSXSXnXnXSXSXnXSXSXnXSXSXnXnXSXnXSXSXnXnXSXSXnXnXSXnXSXSXSXnXSXSXnXSXnXSXnXSXnXnXSXSXnXSXSXnXSXSXnXSXSXSXnXSXSXnXSXSXnXSXnXSXSXnXSXSXnXnXSXSXnXSXSXnXSXSXnXSXSXnXSXSXnXnXSXSXnXnXSXnXSXnXSXnXSXSXnXSXSXSXnXSXSXnXSXSXnXnXSXnXSXSXnXnXSXSXnXnXSXSXnXSXnXSXnXnXp.: X X X X X X X X X X X X X X ; p.nXSXnXSXnXnXSXnXnXSXnXSXnXSXSXnXSXSXnXSXSXnXSXnXSXnXSXSXnXnXSXnXSXSXnXSXSXnXSXnXSXSXSXnXSXnXSXnXSXnXnXSXnXnXSXnXnXSXnXSXnXSXSXnXSXSXnXSXSXnXSXSXSXnXSXSXnXSXSXnXSXnXSXnXSXSXnXSXnXnXSXSXnXSXnXSXnXSXSXnXSXSXnXSXSXnXSXnXSXnXSXSXnXnXSXnXSXSXnXSXnXSXnXSXSXnXSXSXnXSXSX", -"nXSXnXnXSXSXnXSXSXSXnXSXnXnXSXSXnXSXSXnXSXSXnXSXSXSXnXSXSXnXSXSXnXnXSXnXSXSXnXSXSXSXnXSXSXnXSXSXnXnXSXSXnXSXnXnXnXSXnXnXSXSXnXSXnXSXnXnXSXnXSXSXSXnXSXSXnXnXSXSXnXSXnXnXSXSXnXSXSXSXnXSXSXnXSXSXSXnXSXSXnXSXnXnXnXSXnXnXSXSXnXSXSXnXSXSXnXSXSXnXnXSXSXnXSXSXnXSXSXSXSXnXvXa.= X X X X X X X X X X X X X X X X ; p.lXnXSXSXSXSXSXSXSXSXSXnXSXnXSXSXnXSXnXnXSXnXSXSXnXSXSXSXnXnXSXSXSXSXnXnXSXnXSXSXnXnXSXnXSXSXnXnXSXSXSXSXSXnXSXSXSXSXSXnXSXnXSXnXSXSXnXnXSXnXSXSXnXnXSXSXnXnXSXnXSXSXnXnXSXSXnXnXSXSXSXSXnXnXSXSXSXnXSXnXSXSXnXnXSXnXSXSXnXSXSXSXnXnXSXSXSXSXnXnXSXSXnXnXSXSXnXSXnXnXSXSXnX", -"SXnXnXSXnXSXSXnXnXSXSXnXnXSXSXnXSXnXnXSXnXnXSXnXnXnXSXnXnXSXSXnXSXnXnXSXnXnXnXSXnXnXnXSXnXSXSXnXnXSXSXnXSXnXnXSXSXnXnXSXnXSXSXnXSXnXnXSXnXSXSXnXnXSXSXnXnXSXSXnXSXnXnXSXnXSXSXnXnXnXSXnXnXSXSXnXnXSXSXnXSXnXnXSXSXnXnXSXnXSXSXnXnXSXSXnXSXnXnXSXSXnXnXSXnXnXnXSXnXnXnXSXSXnXlXi.= X X X X X X X X X X X X X X + p.lXSXSXSXnXnXSXnXSXnXnXnXSXSXnXSXnXnXSXnXnXSXSXSXnXnXSXSXnXnXSXSXSXnXnXSXnXSXnXSXnXnXSXnXSXnXnXSXnXnXSXSXnXSXnXSXSXnXnXnXSXSXnXnXSXnXSXnXnXSXSXnXSXnXSXSXnXnXSXSXSXnXnXSXnXSXnXnXSXSXnXnXSXnXSXnXSXnXnXnXSXnXSXnXnXSXSXSXnXnXSXSXnXSXnXSXSXnXnXnXSXSXnXnXSXSXnXnXnXSXSXnXSXnXnX", -"SXnXSXnXnXnXnXSXnXnXnXSXnXnXnXnXSXnXSXnXnXSXnXSXnXSXnXSXnXnXnXnXSXnXSXnXnXSXnXSXnXSXnXSXnXnXnXSXnXnXnXnXSXnXSXnXSXnXSXnXnXnXnXSXSXnXSXnXnXnXnXSXnXnXnXSXnXnXnXnXSXnXSXnXnXnXnXSXnXSXnXSXnXnXnXnXnXnXnXnXSXnXSXnXSXnXSXnXnXnXnXSXnXnXnXnXSXnXSXnXSXnXSXnXnXSXnXSXnXSXSXnXnXSXnXnXlXt.+ X X X X X X X X X X X X X X X X X X X X X + p.kXvXSXnXnXnXnXSXnXnXnXSXnXnXnXSXnXnXSXnXnXSXnXnXnXnXSXnXnXnXnXSXnXnXnXnXSXnXnXSXnXnXSXnXnXSXnXnXSXnXSXnXnXnXnXnXSXnXnXSXnXnXnXSXnXnXSXnXnXnXSXnXnXSXnXnXnXnXnXSXnXnXnXnXSXnXSXnXnXSXnXnXSXnXnXSXnXnXnXnXSXnXSXnXnXnXSXnXnXnXSXnXnXnXnXnXSXnXnXnXSXnXnXSXnXSXnXnXSXnXSXnXnXSXnXnXSX", -"nXnXSXnXnXSXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXnXSXnXnXSXnXnXSXnXnXSXnXnXnXSXnXnXnXnXnXSXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXnXSXnXnXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXSXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXSXnXnXSXnXnXSXSXnXiX' O X X X X X X X X X X X X X X X O ' kXnXnXvXnXnXnXnXSXSXnXnXnXSXnXnXnXnXnXSXnXnXSXnXSXnXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXSXnXnXnXnXnXSXnXSXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXnXSXnXnXnXnXSX", -"nXnXnXnXnXnXnXnXnXSXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXSXnXnXnXnXnXnXnXnXnXnXnXnXSXnXSXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXSXnXnXnXnXSXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXSXnXnXSXnXSXSXnXnXnXnXnXnXnXnXnXSXnXnXSXSXnXnXSXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXSXSXiX' O X X X X X X X X X X X . ' iXvXnXnXnXnXnXnXSXnXnXnXnXSXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXnXSXnXnXSXSXnXSXnXnXSXnXSXnXnXSXnXnXnXnXnXnXSXnXnXSXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXSXnXnXnXSXSXnXnXnXnXnXSXnXnXnXnXnXSXnXnXSXnXnXnXnXnXSXnXnXnXnXnXSXSXnXnXnXSXnXnXSXnXnXSXnXnXnXSXnXnXnXnXnXnXnX", -"nXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXSXSXnXSXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXiX) . X X X X X X X X X X X X X X X X X ) iXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnX", -"nXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXSXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXbXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXvXnXiX) X X X X X X X X X X X X X X X X X X ) iXnXnXnXvXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnX", -"nXnXnXnXbXnXnXnXnXnXbXnXnXbXnXnXnXbXnXnXbXnXnXbXnXbXnXnXnXbXnXbXnXnXnXbXnXnXbXnXnXbXnXnXbXnXbXnXbXnXbXnXnXnXbXnXbXnXnXnXbXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXbXnXnXbXnXnXnXnXbXnXnXnXbXnXnXbXnXnXbXnXnXnXbXnXbXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXvXvXrX! X X X X X X X X X X X X V rXSXnXnXnXnXnXnXnXnXnXbXnXnXbXnXbXnXnXnXbXnXnXnXnXnXnXnXbXnXnXnXnXbXnXnXnXnXbXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXbXnXnXbXnXnXbXnXnXbXnXnXnXnXbXnXnXnXbXnXnXnXnXnXnXnXbXnXnXnXbXnXnXnXnXnXnXnXbXnXnXnXbXnXnXbXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnX", -"nXnXnXnXnXnXnXbXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXbXnXnXbXbXnXnXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXbXnXvXnXnXnXbXnXnXbXnXnXnXbXbXnXnXnXvXvXnXnXrX! X X X X X X X X X X X X X X X ! rXnXnXnXnXnXnXbXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXnXbXnXnXnXnXnXnXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXbXbXnXnXnXnXnXbXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXbXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXnXbXnXbXnXnXbXnXnXbXnXnXnXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXbXnXnXbXnXnXbXnXnXnXnXnXnXnXnXbXnXbXnXnX", -"nXnXbXnXnXnXnXbXbXnXnXnXnXnXbXnXnXnXbXnXnXnXnXbXbXnXnXnXnXnXbXnXnXbXnXnXbXnXnXbXbXnXnXnXnXnXnXnXbXbXnXnXbXnXbXnXnXnXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXnXnXbXnXnXbXnXnXnXbXnXnXnXnXbXbXnXnXnXnXnXbXbXbXnXnXnXbXnXbXnXbXnXnXnXnXnXnXnXbXnXnXnXnXbXbXnXnXnXnXnXbXnXnXnXvXnXbXnXnXnXnXnXnXbXbXnXnXnXnXbXnXvXbXbXnXnXwXn X X X X X X X X X X X X X d wXbXnXbXnXnXvXnXbXnXnXnXnXnXbXnXnXnXnXnXbXnXbXnXbXbXnXnXnXbXnXnXbXbXnXbXnXnXbXnXnXnXnXbXnXnXnXnXnXbXnXnXnXnXbXnXnXnXnXbXnXnXnXnXbXnXbXnXnXnXnXnXbXbXnXnXbXnXbXnXbXbXnXbXnXnXnXnXnXnXnXbXnXnXnXnXnXbXnXbXnXnXbXnXnXnXnXnXbXnXnXnXnXnXnXbXnXnXnXnXnXnXbXnXnXnXnXbXnXnXbXnXnXbXnXbXnXbXnXnXbXnXbXnXnXnXnXnXnXbXnX", -"bXnXnXbXbXbXnXnXnXnXbXbXbXnXnXnXbXnXnXbXbXnXbXnXnXnXbXbXbXnXnXbXbXnXnXbXnXnXbXnXnXnXbXbXbXnXbXnXnXnXbXnXnXnXbXnXbXnXbXnXnXbXbXnXbXnXnXbXbXbXnXbXnXbXnXnXnXnXnXbXbXnXnXbXbXbXnXnXnXnXbXbXbXnXnXnXnXbXbXnXnXnXbXnXnXnXbXnXbXnXbXnXnXbXbXnXnXnXnXbXbXnXbXnXnXbXbXnXnXvXnXbXbXbXnXbXnXbXnXnXnXbXbXnXnXvXnXnXbXbXnXbXwXs X X X X X X X X X X X X X X X X X j wXbXbXnXnXnXnXbXvXnXbXnXnXnXbXbXnXbXnXnXbXnXnXnXbXnXnXbXnXnXbXnXnXbXnXnXnXnXbXnXnXnXbXbXnXnXbXbXnXbXnXnXbXbXbXnXnXbXnXbXnXnXbXbXnXbXnXnXbXnXbXnXbXnXnXnXbXnXbXnXnXnXnXnXbXnXnXbXbXnXbXnXbXnXbXbXnXnXnXnXbXnXnXbXnXnXbXnXbXnXnXnXbXbXnXbXnXnXbXbXnXbXnXbXnXbXnXbXnXnXnXbXnXnXbXnXnXbXnXnXnXbXnXnXbXnXbXbXnXbXbXnXbX", -"nXbXbXnXbXnXbXnXnXbXbXnXnXbXnXbXnXbXnXnXbXnXbXnXbXnXbXnXbXbXbXbXnXbXnXbXbXbXnXbXbXnXbXnXbXnXnXbXnXbXnXbXbXbXnXbXbXnXbXbXbXnXbXbXnXbXbXnXnXnXbXnXnXbXbXnXnXbXnXbXnXbXbXnXbXnXbXnXnXbXbXnXnXbXnXbXbXbXnXbXbXbXnXbXbXnXbXbXbXnXbXnXbXbXnXbXbXbXnXbXbXnXbXbXbXnXbXnXbXnXbXnXnXnXbXnXnXbXnXbXnXbXbXnXbXnXbXnXnXbXbXnXnXbX3Xi X X X X X X X X X X X X X i 3XbXnXnXbXnXbXbXbXnXbXnXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXnXbXbXnXbXbXnXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXbXbXnXnXnXnXnXbXnXbXbXbXnXbXbXnXbXnXbXbXnXnXbXnXbXbXnXbXnXbXbXnXbXnXbXnXbXbXbXbXnXbXnXbXnXnXbXbXnXnXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXnXbXnXbXbXnXbXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXbX", -"bXbXnXbXnXnXnXbXbXnXnXbXbXnXbXnXbXnXbXbXnXbXnXbXbXnXnXbXnXnXbXnXbXnXbXnXnXnXbXnXnXbXnXbXnXbXbXnXbXnXbXnXnXbXnXnXnXbXnXbXnXbXnXbXbXbXnXbXnXbXnXbXbXnXnXbXbXnXbXnXbXbXnXnXnXbXbXnXbXnXnXbXbXnXbXnXnXnXbXnXnXnXbXnXnXbXnXbXnXbXnXbXnXnXbXnXbXnXnXnXnXbXbXnXnXbXnXbXbXbXnXbXbXbXnXbXbXnXbXnXbXbXnXbXnXbXnXbXbXnXnXbXbXnXbXbXc.6 X X X X X X X X X X X X X X X X X 9 3XbXnXbXbXbXnXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXbXnXbXnXbXnXbXnXnXbXnXbXbXnXbXnXbXnXbXnXnXbXnXbXnXbXnXbXnXbXbXnXnXnXbXbXbXbXnXbXbXnXnXbXbXnXbXnXbXnXbXnXbXnXbXnXnXbXnXbXbXnXbXnXbXbXbXnXbXnXbXbXnXbXbXbXbXnXnXbXbXnXbXnXbXnXbXnXbXnXbXnXnXbXnXbXbXnXbXnXnXbXnXbXbXnXbXbXnXbXnXbXnXbXnXbXnXbXbXnXbXnXnXbX", -"nXbXbXnXbXbXbXbXnXbXnXbXbXnXnXbXbXnXbXnXnXbXbXnXnXbXnXbXbXbXnXbXbXnXnXbXbXnXbXnXnXbXnXbXbXbXnXbXbXnXbXnXnXbXbXnXbXnXnXbXbXbXnXbXnXbXbXnXbXbXbXbXnXbXbXnXbXnXbXbXnXbXnXbXbXnXnXbXnXbXnXbXbXnXbXbXbXbXnXbXbXnXbXnXbXnXbXbXbXbXnXbXbXbXbXnXnXbXbXnXbXnXbXbXbXbXbXbXnXbXbXnXnXbXbXbXbXbXbXnXnXbXbXnXbXbXnXbXnXbXbXbXvXbXbXbXvXvXc.> X X X X X X X X X X X X 6 c.vXbXnXbXnXbXbXnXbXbXbXnXbXnXbXbXbXnXnXbXbXnXbXbXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXbXbXbXbXnXbXnXbXnXbXbXnXbXbXnXnXbXbXnXbXbXbXbXnXnXbXnXbXbXbXnXnXbXbXnXnXbXbXbXbXbXnXbXbXnXbXbXbXbXbXbXbXnXbXnXbXnXbXnXbXbXbXbXnXbXbXnXbXnXnXbXnXbXnXbXbXnXnXbXbXnXbXnXbXbXbXbXbXnXbXnXnXbXnXbXbXbXnXnXbXbXbXbXbXbXbXbXbXbXnXbXbXbXnXbXnXbXbXbX", -"bXbXbXnXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXbXnXnXbXbXbXbXbXnXbXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXnXbXbXbXbXbXbXnXbXbXbXvXbXbXvXbXlXa.; X X X X X X X X X X X ; a.kXvXbXvXbXbXbXbXbXbXnXbXbXbXbXbXnXbXbXbXbXbXbXnXbXnXbXbXbXvXbXbXbXbXbXbXbXnXbXnXbXnXnXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXnXbXbXbXbXbXbXnXbXnXbXnXbXbXbXbXbXbXbXbXnXnXbXnXbXbXbXnXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXnXbXbXnXbXbXnXbXbXbXnXbXbXbXbXbXbXnX", -"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXkXa.; X X X X X X X X X X . - a.bXbXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXnXbXbXbXbXbXbXbXbXbXbXnXbXbX", -"bXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXkXt.+ X X X X X X X X X X X X + t.jXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX", -"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXkXt.O X X X X X X X X X X X X X + t.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXnXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX", -"bXbXcXbXbXbXbXbXbXcXbXbXcXbXbXbXbXcXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXcXcXbXbXbXbXbXbXbXbXbXcXbXbXbXcXbXbXbXbXcXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXcXbXbXcXbXbXbXbXcXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXcXbXcXbXbXbXbXbXbXbXbXbXcXbXbXcXbXbXbXcXbXcXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXcXbXcXbXbXbXbXbXcXbXbXbXcXbXbXbXbXbXbXcXbXbXbXcXbXbXbXbXbXjX' @ X X X X X X X X o ' iXbXcXbXbXbXbXbXcXbXbXbXbXcXbXbXbXcXbXbXbXbXbXcXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXcXbXbXbXcXbXbXbXbXbXbXcXbXbXbXbXbXcXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXcXbXbXbXcXbXbXbXcXbXbXcXbXbXbXbXbXbXbXcXbXbXbXbXcXbXbXcXbXbXbXbXcXbXbXcXbXbXbXbXbXcXbXbXbXcXbXbXbXbXbX", -"bXcXcXbXbXbXbXcXbXbXcXbXbXbXcXbXbXcXbXbXbXcXbXbXcXbXbXbXbXcXcXbXcXbXbXbXbXcXcXbXbXbXbXcXbXcXbXbXcXbXbXbXbXbXcXbXcXbXbXbXcXbXbXbXbXcXcXbXbXbXbXcXbXbXcXbXbXbXcXbXbXcXbXbXbXcXbXbXcXbXbXbXbXcXbXcXcXbXbXbXcXbXbXbXbXbXbXbXcXbXbXbXbXbXbXbXbXbXbXcXbXbXbXbXcXbXbXbXbXcXbXcXbXbXbXcXbXcXbXbXbXbXbXcXcXbXbXbXbXbXcXbXcXbXbXbXcXbXbXbXbXcXcXbXbXbXbXcXcXiX' X X X X X X X X X X X X X X X X . ` iXbXbXbXbXcXcXbXbXbXbXbXcXbXbXbXcXbXbXcXbXbXbXbXcXbXbXbXbXcXbXcXbXbXbXbXcXbXcXbXbXbXbXcXbXbXbXbXbXcXbXcXbXbXbXbXbXcXcXbXbXbXbXcXbXcXbXbXcXbXbXbXbXbXcXbXbXbXbXbXcXbXcXbXbXbXcXbXbXbXcXbXbXbXbXbXcXbXcXbXbXbXbXbXcXbXbXbXcXbXbXbXcXbXbXcXbXbXbXcXbXbXbXbXcXbXbXbXcXbXbXbXcXbXcXbXbXbXbXbXbXcXcXbXbXbXbXbXbXcXbXcXbXbXbXbXbXcXbXbXbXbXcXbXbXbXcXbXbXcX", -"cXbXbXbXbXcXbXcXcXcXbXbXcXbXcXbXbXcXbXcXbXbXcXbXcXbXcXbXcXbXbXcXcXbXcXbXcXbXbXbXcXcXbXbXcXbXbXcXbXbXcXbXcXcXbXbXbXcXcXbXcXbXcXbXbXbXbXbXbXcXbXcXcXcXbXbXcXbXcXbXbXcXbXcXbXbXcXcXcXbXcXbXcXbXbXcXcXbXcXbXcXbXcXbXcXbXcXcXbXcXbXcXcXbXcXbXcXcXbXbXbXcXbXcXbXcXcXbXbXbXbXcXbXcXbXcXbXbXcXbXcXbXcXbXbXbXcXbXcXcXbXbXbXcXcXbXcXbXcXbXcXbXbXbXbXcXbXcXbXcXcXiX) X X X X X X X X X X X X X X X X ) iXcXcXcXbXcXcXbXbXcXcXbXcXcXbXbXcXbXbXcXbXcXcXbXcXcXbXbXcXcXbXbXcXbXbXcXcXbXbXcXbXbXcXcXcXbXbXcXcXbXcXbXcXbXbXcXcXbXcXbXcXbXcXbXcXbXbXcXcXcXbXbXbXcXbXcXbXbXcXbXcXcXbXbXbXcXcXbXcXbXcXbXbXcXbXcXcXbXbXcXbXcXbXcXcXbXbXcXcXcXbXbXcXbXbXcXbXcXbXcXbXbXcXcXcXcXbXbXcXbXcXbXbXcXbXcXbXbXcXcXcXbXcXbXbXcXcXbXcXbXcXbXbXcXcXbXbXcXbXcXbXcXcXbXbXbXcXcXbXcXcXbX", -"bXcXbXcXcXbXcXbXbXbXbXcXbXcXbXcXbXbXcXbXcXbXbXcXbXcXbXcXbXcXbXbXbXbXbXbXbXcXbXcXbXcXcXbXbXbXcXbXbXcXbXcXbXcXbXcXbXbXbXbXbXcXbXcXbXcXbXcXcXbXcXbXbXbXbXcXbXbXbXcXbXbXcXbXcXbXbXbXbXcXbXcXbXcXbXbXbXbXbXbXbXcXbXcXbXcXcXbXbXbXcXbXbXcXbXcXbXcXcXbXcXbXcXbXbXbXbXbXcXbXcXbXcXbXcXbXcXbXbXcXbXcXbXcXbXcXbXcXbXcXbXcXbXbXbXbXbXcXbXcXbXcXbXcXcXbXcXbXcXbXbXcXbXrX) X X X X X X X X X X ) rXbXbXbXcXbXcXbXbXbXbXbXbXcXbXcXbXcXbXbXbXcXbXbXcXbXbXbXbXcXbXcXcXbXbXbXbXcXcXbXcXbXcXbXbXbXbXbXcXbXbXcXbXbXbXbXbXcXbXcXbXbXbXcXbXcXbXcXcXbXbXcXbXcXbXbXbXcXbXcXbXcXbXcXbXcXbXbXbXbXbXbXbXcXcXbXcXbXcXbXcXbXcXbXcXbXcXbXcXbXbXcXbXcXbXbXbXcXcXbXcXbXbXcXbXbXbXbXbXcXbXbXbXcXcXbXcXbXcXbXbXbXbXcXbXcXbXbXbXcXbXcXbXcXbXbXbXcXcXbXcXbXcXbXcXbXcXbXbXbXbXcXbXbX", -"bXbXcXbXcXbXcXbXcXcXbXcXbXbXcXbXcXcXbXcXbXcXcXbXcXbXcXbXcXbXcXbXbXcXcXcXcXbXcXbXcXbXbXcXbXcXbXcXcXbXcXbXcXbXbXcXcXcXcXcXcXbXcXbXcXbXcXbXcXbXbXcXcXcXcXbXcXbXcXbXcXcXbXcXbXcXcXbXcXbXcXbXcXbXcXbXbXcXcXcXcXbXcXbXbXcXbXcXbXcXbXcXcXbXcXbXcXbXbXcXbXcXbXcXcXcXcXcXcXbXcXbXbXcXbXbXcXcXcXbXcXbXcXbXcXbXcXbXcXbXbXcXcXcXcXcXcXbXcXbXcXbXcXbXbXcXbXcXbXcXcXbXbXcXbXrXV . X X X X X X X X V rXbXbXbXcXcXbXbXcXbXcXcXcXbXcXbXcXbXbXcXcXcXbXcXcXbXcXbXcXcXcXbXcXbXbXcXcXcXbXcXbXcXbXcXbXcXcXbXcXcXbXcXbXcXcXcXcXcXbXcXbXcXcXcXcXbXcXbXcXbXcXbXcXbXbXcXcXcXbXcXcXbXcXbXcXbXbXcXcXcXcXcXcXcXcXbXbXcXbXcXbXcXbXcXbXcXbXcXbXcXbXcXcXbXcXcXcXcXbXcXbXcXbXcXbXbXcXbXcXcXcXbXcXcXcXbXbXcXbXcXbXcXcXbXcXbXcXbXcXbXcXbXcXbXcXbXcXbXcXbXbXcXbXcXbXcXbXcXbXcXcXcXcXbXcXcX", -"bXcXcXcXcXcXcXcXbXcXcXcXbXcXbXcXbXcXcXcXcXbXbXcXcXbXbXcXbXcXbXcXcXcXcXbXcXbXcXbXcXbXcXcXcXcXcXbXcXbXcXbXcXcXbXcXcXcXcXcXcXcXcXbXbXcXbXcXcXcXcXcXbXcXcXcXbXcXbXcXbXcXcXbXcXbXbXcXbXcXbXcXbXcXbXcXcXbXcXbXcXbXcXbXcXcXbXcXcXcXcXbXcXbXcXbXcXcXcXbXcXcXcXbXcXbXcXbXbXcXbXcXcXcXcXcXbXcXcXbXcXbXcXcXcXbXcXbXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXbXcXbXcXbXcXcXcXbXcXbXcXcXcXrXV X X X X X X X X X X V rXcXcXcXcXbXcXbXcXcXbXcXcXcXcXbXbXcXcXcXcXbXcXcXbXbXcXbXcXcXbXcXcXcXcXcXcXbXcXbXcXbXcXbXcXcXcXcXbXcXcXcXbXcXcXcXcXbXcXbXcXbXcXcXbXcXcXcXcXcXcXbXcXcXcXbXbXcXbXcXcXcXcXbXcXbXcXcXbXcXbXcXbXcXcXcXcXcXcXcXcXbXcXbXcXcXcXcXbXbXcXcXcXbXcXcXcXbXcXbXcXbXcXbXcXcXcXcXbXcXbXcXbXcXcXbXcXbXcXbXcXcXcXcXbXcXcXbXcXcXbXcXbXcXbXcXcXcXcXbXbXcXbXcXbXcXbXcXbXcXcXcXcXbXcXbXcXcX", -"cXcXbXcXcXbXcXbXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXbXcXcXcXbXcXbXcXbXcXcXcXcXcXcXcXbXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXbXcXcXcXbXcXcXbXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXbXcXcXcXcXbXcXcXcXcXcXcXcXcXcXbXcXcXbXcXbXbXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXbXcXcXcXzXwXn X X X X X X X X X X j wXcXzXcXcXcXcXbXcXcXbXcXcXcXcXbXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXbXcXcXcXbXcXcXcXcXbXcXbXcXcXcXbXcXcXcXcXbXcXcXcXbXcXcXbXcXcXcXcXbXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXbXbXcXcXbXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXbXcXcXcXbXbXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXbXcXcXcXcXcXbXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXbXcXcXbXcX", -"cXcXcXbXbXcXcXcXcXbXcXcXcXcXbXcXbXcXcXcXcXcXbXcXcXcXbXcXcXcXcXcXbXcXcXcXcXbXcXcXcXcXbXcXcXcXcXcXcXbXcXcXcXcXcXbXbXcXcXcXbXcXcXcXcXcXcXbXbXcXcXcXcXbXcXcXcXcXbXcXcXbXcXcXcXcXbXcXcXcXbXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXbXbXcXcXcXcXbXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXcXbXcXcXcXcXcXbXcXcXcXcXbXcXcXcXcXbXcXcXcXcXcXcXbXcXcXcXbXcXcXcXcXcXcXbXcXwXe . X X X X X X X X j wXzXzXcXbXcXbXcXcXcXbXcXcXcXbXcXcXcXcXcXbXcXcXcXcXcXcXcXbXcXcXcXbXcXbXcXcXcXcXbXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXbXcXcXcXcXcXcXcXcXcXbXbXcXcXcXbXcXcXcXcXbXcXcXcXcXcXbXcXbXcXcXcXcXcXbXcXcXcXbXcXcXcXcXcXcXcXbXbXcXcXcXcXcXbXcXbXcXcXbXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXbXcXcXcXbXcXcXcXcXcXcXcXbXcXcXcXcXcXbXbXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXcXcXbXcXcXcX", -"cXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXzXv.i X X X X X X X i C.zXcXcXcXzXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXbXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcX", -"cXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXbXzXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXbXxXcXcXcXcXcXcXzXv.t X X X X X X X X X X X X X X t v.zXzXcXcXzXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXzXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXxXcXcXcX", -"cXcXcXcXcXcXcXxXxXcXcXcXcXcXcXcXcXcXcXxXcXxXcXcXcXcXzXzXcXxXcXcXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXxXcXcXcXxXcXzXzXzXzXcXcXcXxXcXcXcXcXcXcXcXxXxXcXcXcXcXcXcXcXcXcXxXcXcXcXxXcXcXcXzXzXcXxXcXcXcXcXxXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXxXcXzXzXzXzXcXcXxXcXcXzXzXzXcXcXcXcXxXcXcXcXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXcXxXzXzXcXcXcXcXxXcXcXcXxXcXcXcXcXzXxXcXcXcXcXcXcXxXzXzXxXc.5 X X X X X 6 c.cXcXcXcXcXzXzXcXcXxXcXcXcXxXcXzXzXzXzXcXcXcXxXcXxXcXcXzXzXcXcXcXxXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXxXcXcXzXzXcXcXcXxXcXcXcXzXzXzXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXcXxXcXxXcXcXcXcXcXcXcXcXxXcXcXcXxXcXcXzXzXzXcXcXcXcXxXcXcXcXzXzXzXcXcXcXcXcXcXcXcXxXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXxXcXcXxXcXcXcXcXcXxXcXcXcXxXcXcXcXcXzXzXcXcXcXxXxXcXcXcXcXcXcXcXcXxXcXcXxXcXcXcXcXcXxXcX", -"cXcXcXxXcXxXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXxXcXzXzXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXzXzXcXcXxXcXcXcXcXxXcXxXcXcXcXcXcXcXxXcXcXcXcXcXxXcXcXcXcXcXcXcXzXzXcXcXcXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXxXcXcXcXcXcXcXxXcXcXcXcXzXcXcXcXxXcXcXcXcXcXcXxXcXcXcXcXxXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXxXxXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXzXzXzXzXcXcXcXcXxXcXcXcXcXzXzXzXzXa.; X X X X X X X X X X 5 a.zXxXzXzXcXzXzXzXzXcXcXcXxXcXcXcXcXcXcXzXzXxXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXcXcXzXcXcXcXcXcXcXcXcXcXzXzXcXcXxXcXcXcXcXcXcXxXcXcXcXcXxXcXcXcXxXcXcXcXcXcXcXxXcXcXcXcXcXxXcXcXcXcXcXcXzXzXcXxXcXcXcXcXcXcXxXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXzXzXcXxXcXcXcXcXcXcXxXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcX", -"cXxXcXcXcXcXxXcXcXxXxXcXcXcXcXxXcXcXxXcXcXxXxXcXcXcXcXzXcXxXcXcXxXcXxXcXxXcXcXcXcXxXcXxXcXxXcXcXxXcXcXcXcXxXcXxXcXxXcXcXxXcXcXcXcXxXcXcXcXcXxXcXcXxXxXcXcXcXcXxXxXcXcXcXcXxXcXxXcXxXcXcXcXcXxXcXxXcXxXcXcXxXcXxXcXcXcXxXcXxXcXcXcXxXcXxXcXcXcXxXcXxXcXcXxXcXcXcXcXxXcXzXcXcXxXcXxXcXcXcXxXcXcXxXxXcXcXcXcXxXcXxXcXxXcXcXcXcXxXcXxXcXcXxXxXcXcXcXcXxXcXxXcXzXzXxXcXxXcXxXcXcXcXcXxXzXzXzXzXxXxXa.; X X X X X X X X ; a.xXcXzXzXzXxXzXzXzXzXzXxXcXcXcXcXxXcXxXcXxXcXcXcXcXxXcXcXxXxXcXzXzXcXxXcXxXcXxXcXcXcXcXxXcXxXcXcXxXcXxXcXxXcXxXzXzXxXcXcXxXcXxXcXxXzXxXcXxXcXcXcXxXcXxXcXcXcXxXcXxXcXcXxXcXcXcXcXxXxXcXcXcXcXxXxXcXcXcXcXxXcXxXcXxXcXcXcXcXxXcXxXcXxXcXcXcXcXxXcXxXcXxXcXcXcXcXcXxXcXxXcXxXcXxXxXcXxXcXxXcXcXcXcXxXcXxXcXcXcXcXxXcXxXcXxXcXxXcXcXxXxXcXcXxXcXcXcXcXxXcXcXxXxXcXcXcXcXxXcXcXxXcXxXcXcXcXcXxXcXcX", -"xXcXcXxXcXxXcXcXcXcXxXcXxXcXcXxXcXxXcXxXcXcXxXcXxXcXxXcXcXcXcXxXxXcXxXcXxXcXxXcXcXcXcXxXxXcXxXcXxXcXxXcXcXcXcXxXcXcXxXcXxXcXxXcXxXcXcXxXcXxXcXxXcXcXxXcXxXcXcXxXcXxXcXxXcXcXxXcXxXcXcXcXxXcXxXcXcXcXxXcXxXcXxXcXxXcXcXxXcXcXxXcXxXcXxXcXxXcXcXxXcXcXxXcXxXcXxXcXxXcXcXxXcXxXcXcXcXcXxXcXxXcXcXxXcXxXcXxXcXcXxXcXcXxXxXcXcXcXcXxXcXcXxXcXxXcXxXcXxXcXxXcXcXxXcXcXxXcXcXcXxXcXxXcXcXxXcXxXcXcXcXcXfXt.+ X X X X X X X X X X $ t.jXcXcXxXcXxXcXxXcXxXcXcXxXcXcXxXcXxXcXxXcXcXcXcXxXcXcXxXcXxXcXxXcXcXxXcXxXxXcXxXcXcXxXcXcXcXcXcXcXcXcXcXcXxXcXxXcXcXcXcXcXcXcXxXcXcXcXcXxXcXcXxXcXxXcXcXcXxXcXxXcXcXxXcXxXcXcXcXcXxXcXxXcXcXxXcXxXcXxXcXcXcXxXcXxXcXxXxXcXcXcXcXxXcXxXcXxXcXxXcXxXcXxXcXcXcXxXcXxXcXcXcXcXxXcXxXcXcXcXcXcXxXcXxXcXcXcXcXcXxXcXxXcXcXcXcXcXxXcXxXcXxXcXcXcXxXcXxXcXcXxXcXcXcXxXcXcXxXcXxXcXcXxXcXcXcXxXcXxXcXxXcXxX", -"cXxXzXxXxXcXxXxXxXxXcXxXcXxXzXxXxXcXxXcXxXzXcXxXzXxXzXzXxXxXxXcXcXxXcXxXcXxXcXxXxXxXxXcXcXxXcXxXcXxXcXxXxXxXxXcXxXxXcXxXcXxXcXxXcXxXzXxXxXcXxXcXxXcXxXcXcXxXzXxXxXcXxXcXxXzXxXzXcXxXxXzXcXxXcXxXxXcXcXxXcXxXcXxXcXxXcXxXxXxXcXxXcXxXcXxXcXxXcXxXxXcXxXcXcXxXcXxXxXxXzXxXxXcXxXxXxXxXcXxXcXxXzXxXxXcXxXcXxXzXzXxXcXxXzXzXxXxXxXcXxXcXxXcXcXxXcXxXcXxXcXxXzXxXxXzXxXxXxXxXcXxXcXxXxXcXxXcXxXxXxXcXcXcXjXt.+ X X X X X X X + t.jXxXxXxXxXcXxXcXxXcXxXcXxXcXxXxXxXcXxXcXxXcXxXxXxXcXxXxXcXcXxXcXxXcXxXxXcXxXzXxXcXxXzXxXcXxXxXxXxXxXxXxXxXxXxXcXxXcXxXxXxXxXxXxXxXcXxXxXxXxXzXxXzXcXxXcXxXxXzXcXxXzXxXxXcXxXcXxXxXxXcXxXcXcXxXxXcXxXcXxXcXxXxXcXxXxXcXxXcXzXzXxXxXcXxXxXcXxXcXxXcXxXcXxXcXxXxXxXcXxXcXxXxXxXxXcXxXcXxXxXxXxXxXcXxXcXxXxXxXxXxXcXxXcXxXxXxXxXxXcXxXcXxXcXxXxXzXxXcXcXxXcXxXxXxXxXcXxXzXxXcXcXxXzXxXxXxXxXcXzXxXxXcXxXcX", -"xXxXzXzXxXzXcXxXxXcXcXxXxXxXcXzXxXzXcXxXzXxXzXxXxXzXxXxXzXxXxXcXxXcXcXxXxXcXcXcXcXxXxXcXxXcXcXxXxXxXcXcXcXxXxXcXxXcXcXxXxXxXcXcXxXxXcXzXxXzXcXxXcXxXcXxXxXxXcXzXxXzXcXxXzXxXzXxXxXxXzXxXzXxXxXzXcXxXcXxXxXxXcXcXcXxXxXcXxXcXcXxXxXxXcXcXcXxXxXcXcXxXcXxXxXxXcXcXcXzXzXzXxXzXcXxXxXcXcXxXxXxXcXzXxXzXcXxXzXxXxXzXxXzXxXxXzXxXxXcXcXxXcXxXxXxXcXcXcXxXxXcXxXzXzXxXcXcXxXcXxXcXxXcXcXxXxXcXcXcXxXxXzXzXxXxXiX` O X X X X X X X X + ` uXxXcXzXxXxXcXcXxXxXcXcXcXcXxXxXcXxXcXcXxXxXxXcXcXcXxXxXcXcXxXcXxXxXxXcXcXcXxXxXzXcXxXzXxXcXxXcXxXxXcXxXcXxXcXxXcXxXcXxXcXcXxXcXxXxXcXxXcXxXzXzXxXzXxXxXzXxXxXzXxXxXzXxXzXcXxXxXcXcXcXcXxXxXcXxXxXcXxXxXxXxXcXcXxXcXxXxXcXcXcXxXxXzXxXxXcXcXxXxXcXcXcXcXxXxXcXcXxXcXxXxXxXxXcXxXcXxXcXxXcXcXxXxXxXxXcXxXcXxXcXxXxXxXcXxXcXxXcXxXcXxXcXxXcXxXxXzXzXzXzXxXxXcXxXxXcXcXcXxXxXzXzXxXxXzXzXxXzXzXzXxXzXxXzXcXxX", -"xXcXxXxXzXxXzXxXcXxXxXcXxXcXxXxXzXxXzXxXxXzXxXzXxXzXxXzXxXzXxXxXcXxXxXcXxXcXxXxXxXcXxXxXcXxXxXxXxXcXxXxXxXcXxXxXcXxXxXcXxXcXxXxXxXcXxXxXzXxXzXxXxXxXxXcXxXcXxXxXxXxXzXxXxXzXxXzXxXzXxXzXxXzXxXxXxXxXxXcXxXcXxXxXxXcXxXxXcXxXxXcXxXcXxXxXxXcXxXxXxXxXxXcXxXcXxXxXxXxXxXxXzXxXzXxXcXxXxXcXxXcXxXxXzXxXzXxXxXzXxXzXzXxXxXzXxXzXxXxXxXxXxXcXxXcXxXxXxXcXxXxXzXxXxXcXxXxXcXxXcXxXxXxXxXxXcXxXxXxXcXxXzXxXxXxXxXcXuX` O X X X X X . ` uXzXzXcXxXzXxXcXxXxXcXxXcXxXxXxXcXxXxXcXxXxXxXxXcXxXxXxXcXxXxXxXxXxXcXxXcXxXxXzXxXzXxXxXzXxXzXcXxXxXcXxXxXxXcXxXxXcXxXxXxXcXxXxXxXxXcXxXxXxXxXzXxXzXxXxXzXxXzXxXzXxXzXxXzXxXxXxXxXcXxXxXxXcXxXcXxXxXcXxXxXcXxXxXxXcXxXxXcXxXxXxXxXxXzXxXzXxXxXxXcXxXxXxXxXxXcXxXxXxXcXxXcXxXxXxXxXcXxXxXxXcXxXcXxXxXcXxXxXcXxXxXxXcXxXxXxXcXxXxXcXxXcXxXxXcXxXxXcXxXxXxXxXxXzXxXcXxXxXxXxXxXcXxXxXxXzXxXxXzXxXxXxXzXxXzXxXzXxX", -"xXxXxXxXxXxXxXzXxXxXxXxXcXxXxXxXxXxXxXxXzXxXxXxXxXzXxXxXxXzXxXxXxXxXxXxXxXcXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXzXxXcXxXxXxXxXxXxXzXxXxXxXxXzXxXxXxXzXxXxXxXzXxXxXxXxXxXxXcXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXcXxXxXcXxXxXxXxXxXxXxXxXxXxXxXxXxXzXxXxXxXxXcXxXxXxXxXxXxXxXzXxXxXxXxXzXxXxXxXzXxXxXxXcXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXcXxXxXcXxXxXxXxXxXxXcXxXxXxXxXxXxXrXJ X X X X X X X . ) uXxXcXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXcXxXxXcXxXxXxXxXxXxXxXxXzXxXxXxXzXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXxXzXxXxXxXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXcXcXxXxXcXxXxXxXxXcXxXxXzXxXxXxXzXxXxXxXxXxXcXxXxXxXxXxXcXcXxXxXxXcXxXxXcXxXxXxXxXcXxXxXxXxXxXxXxXcXxXxXcXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXzXxXxXxXzXxXxXxXxXxXcXxXxXxXxXxXxXxXzXxXxXxXzXxXxXxXxXxXxXxXzX", -"xXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXrX) . X X X X X X J rXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXcXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXzXxXxXxXzXxXxXxXxXxXxXxXxXxXxXxXxXxXcXcXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXcXxXxXxXcXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX", -"xXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXrXV X X X X X X X V rXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX", -"xXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX'.V X X X X X X X V rXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX", -"xXxXxXxXxXxXhXxXhXxXxXhXxXxXxXxXxXhXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXhXxXhXxXxXxXxXhXxXhXxXxXxXxXxXxXxXhXxXhXxXxXhXhXxXxXxXxXxXxXxXxXhXxXhXxXxXhXxXxXxXxXxXxXxXxXxXhXxXhXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxXxXhXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxXxXhXhXxXxXxXhXxXxXhXxXxXxXxXxXxXhXxXxXxXxXxXxXhXhXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXC.j X X X X X X b C.xXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxXxXhXxXxXxXxXxXhXxXxXxXxXxXxXxXhXxXxXhXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXhXxXhXxX", -"xXxXxXhXxXxXxXxXxXxXxXxXhXxXxXhXxXxXxXhXhXxXhXxXxXxXxXxXxXhXhXxXxXxXhXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXhXxXxXxXxXxXxXhXxXhXxXxXhXxXhXxXhXxXxXxXxXhXxXhXxXxXhXxXhXxXhXxXxXxXxXxXxXxXxXhXxXxXhXxXhXxXxXxXhXxXxXxXxXxXxXhXxXhXxXxXhXxXxXxXhXxXxXxXxXxXxXxXxXxXxXxXhXxXxXxXxXhXxXhXxXxXxXxXxXxXhXhXxXxXxXxXxXhXxXhXxXhXxXhXxXxXhXxXhXxXxXxXxXhXxXxXhXxXhXhXxXxXhXhXxXxXhXhXxXxXhXhXxXhXxXxXxXxXxXxXxXxXxXC.h X X X X X X i C.xXxXxXhXxXhXhXxXxXxXhXxXhXxXxXhXxXhXxXxXxXxXxXxXxXxXxXhXxXxXxXxXxXhXxXxXxXhXxXxXxXxXxXxXxXxXhXxXxXhXhXxXhXxXhXxXxXhXhXxXxXhXxXhXxXhXhXxXhXxXxXhXhXxXhXxXhXxXxXhXxXxXxXxXxXxXhXxXhXxXxXxXxXxXxXhXhXxXhXxXxXhXhXxXhXxXhXxXhXxXxXxXhXxXxXxXxXhXhXxXhXxXhXxXhXxXxXhXhXxXhXxXxXhXxXhXxXhXhXxXxXxXhXxXhXxXhXxXhXxXxXhXhXxXhXxXxXhXxXhXxXhXhXxXhXxXxXhXxXhXhXxXhXxXxXhXxXhXxXhXhXxXhXxXhXxXhXxXxXhXxXxXhXxXhXxXhXxXhXxXhXxXxXxXxXxXxXxXxXxX", -"xXhXhXxXxXhXhXxXxXxXhXxXhXxXhXxXhXxXhXxXxXhXhXxXhXxXhXxXhXxXxXhXxXhXxXxXhXxXhXhXhXxXxXhXhXxXhXxXxXhXhXxXxXhXhXxXxXxXhXxXhXxXhXxXxXhXhXxXxXhXhXxXhXxXxXxXhXxXxXhXhXxXxXxXxXhXhXxXxXxXhXxXxXhXxXhXxXhXhXxXhXxXhXxXhXxXxXhXhXxXxXxXxXhXhXxXxXhXhXxXhXxXxXxXhXxXxXhXxXhXhXxXxXhXhXxXxXxXhXxXhXxXhXxXhXxXhXxXxXhXhXxXhXxXhXxXhXxXxXhXxXhXhXxXxXxXhXxXxXhXxXhXhXxXxXxXhXxXhXxXhXxXhXxXxXxXxXhXhXxXxXhXhXxXxXhXhXxXxXhXxXhXhXxXxXhXhXxXxXhXxXhXv.i X X X X X i v.hXxXxXhXxXxXxXxXxXhXhXxXxXxXhXxXxXxXxXhXxXhXhXxXhXxXhXxXhXxXxXhXhXxXhXxXxXhXhXxXxXhXhXxXhXxXhXxXhXxXxXhXxXhXxXxXxXhXxXhXhXxXxXhXxXhXxXxXxXxXhXxXhXxXxXhXhXxXxXhXxXhXxXxXhXxXhXxXxXhXhXxXhXxXhXhXhXxXxXhXhXxXhXxXxXhXxXxXxXhXhXxXhXxXxXhXhXxXhXxXxXhXhXxXxXxXhXxXhXxXxXhXhXxXxXhXxXhXxXxXxXhXhXxXxXhXxXhXxXxXhXxXhXxXxXhXhXxXxXhXxXhXxXxXxXxXhXxXxXhXxXhXhXxXxXhXxXhXxXxXhXxXxXhXhXxXxXhXxXhXhXxXxXhXxXxXxXhXhXxXxXhXxXhXhXxXxXhXhXxXhXxX", -"hXxXhXxXhXxXxXhXhXhXxXhXxXhXxXxXhXxXxXxXhXxXxXhXxXhXxXhXxXxXhXxXhXxXhXhXxXhXxXxXxXhXhXxXhXxXxXxXhXxXhXxXhXxXxXhXhXhXxXhXxXhXxXxXhXxXxXhXxXhXxXxXxXhXxXhXxXhXxXxXxXhXhXxXhXxXxXxXhXxXxXhXxXxXhXxXxXhXxXhXxXhXxXhXxXhXhXxXxXhXhXxXhXxXxXhXxXhXxXxXxXhXxXhXxXhXxXxXhXxXhXxXhXxXxXhXhXhXxXhXxXhXxXxXhXxXxXxXhXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXhXxXxXhXxXxXhXxXxXhXhXxXxXhXxXhXxXhXxXxXxXxXhXxXxXxXhXxXxXxXhXxXxXxXhXxXhXxXhXxXxXxXxXhXxXxXxXxXxXhXv.6 X X X X 9 v.xXhXxXhXxXxXxXhXhXxXhXxXxXxXhXxXxXhXxXxXhXxXhXxXxXhXxXhXxXhXxXhXhXxXxXhXxXxXhXxXxXhXxXhXxXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXhXxXxXhXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXxXhXxXhXxXhXxXhXxXxXxXhXxXxXhXxXhXxXxXxXhXxXxXxXhXxXxXhXxXxXhXhXxXxXhXxXhXhXxXxXhXxXxXhXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXhXxXhXxXhXxXxXhXxXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXhXxXhXxXhXxXxXhXxXxXhXxXxXxXhXxXhXxXhXxXxXhXxXxXxXxXhXxXxXxXhXxXhXxXhXhXhXxXxXhXxXxXhXxXxXhXhXxXxXhXxXhX", -"xXhXhXxXhXxXhXxXhXxXhXxXhXxXxXhXhXxXhXhXxXhXhXxXxXhXhXxXhXhXxXhXxXhXxXxXhXxXhXxXhXhXxXhXhXxXhXhXxXhXhXxXhXxXhXxXhXxXhXxXhXxXxXhXxXhXhXxXhXxXxXhXhXxXxXhXxXhXxXhXhXhXxXhXhXxXhXhXxXhXhXxXhXxXhXxXxXhXhXxXxXhXhXxXhXhXxXhXhXxXhXhXxXhXhXxXhXxXxXhXhXxXxXhXxXhXxXhXxXhXxXhXhXxXhXxXhXxXhXxXhXxXxXhXhXxXhXhXxXhXxXxXxXhXhXxXhXhXxXhXhXxXhXhXxXxXhXxXhXxXhXxXhXxXhXhXhXxXhXxXhXhXxXhXhXhXxXhXxXhXhXxXhXxXxXhXxXhXxXhXxXhXxXhXhXhXhXxXhXxXhXxXxXhXxXxXc.5 X X X X X 6 c.xXxXhXxXhXhXxXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXhXxXxXhXxXxXxXhXhXxXhXhXxXhXhXxXhXhXxXhXhXxXhXxXxXhXhXxXhXxXhXhXxXhXxXhXhXxXhXxXhXxXhXxXhXhXhXxXxXhXxXhXhXxXhXhXxXhXhXxXhXhXhXxXxXhXhXxXhXhXxXhXxXxXxXhXhXxXhXhXxXhXhXxXhXhXhXxXhXxXxXxXhXxXxXhXxXxXhXhXxXhXxXhXhXxXxXhXhXxXhXhXxXhXhXxXhXhXhXxXxXhXxXxXhXxXxXhXxXxXxXhXhXxXhXhXxXhXhXxXhXhXhXxXxXhXxXhXhXxXhXxXxXhXhXxXhXhXhXxXxXhXhXxXxXhXxXhXxXhXhXhXxXhXhXxXhXxXxXxXhXxXxXhXxXxXhXxXxXhXhXhXxXhX", -"xXhXhXxXhXhXxXhXhXhXxXhXhXhXhXhXxXhXhXxXhXxXxXhXhXxXhXhXhXxXxXhXhXxXhXhXhXhXxXhXhXxXxXhXxXhXhXxXxXhXhXxXhXhXxXhXhXhXxXhXhXhXhXhXxXhXxXhXhXhXhXhXhXhXhXhXhXxXhXxXhXxXxXhXhXxXxXhXhXxXhXhXhXhXhXhXhXxXxXhXxXxXhXhXhXxXxXhXxXhXhXxXxXhXxXhXhXhXhXhXhXhXhXhXhXxXhXxXxXhXhXxXhXhXxXhXhXhXxXhXhXhXhXhXxXhXhXxXhXxXhXhXhXhXxXhXhXxXxXhXhXxXxXhXhXxXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXxXhXxXhXhXhXhXxXhXhXxXhXhXhXhXxXhXhXxXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXgXhXa.; X X X X 5 a.hXhXhXhXxXhXhXxXhXxXhXxXxXhXhXxXxXhXhXxXhXhXhXhXhXhXhXxXhXhXhXhXxXhXhXxXxXhXxXhXhXxXxXhXhXxXhXhXhXhXhXhXxXhXhXxXhXxXhXxXhXhXhXhXhXhXxXhXhXxXxXhXhXxXhXxXhXhXhXxXxXhXxXhXhXxXxXhXhXhXxXhXhXxXhXxXhXhXhXhXxXhXhXxXxXhXxXhXhXxXxXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXxXxXhXhXxXhXhXhXxXxXhXxXhXhXxXxXhXhXxXhXhXhXhXhXxXhXhXhXxXhXhXhXxXxXhXxXhXhXxXxXhXhXxXhXxXhXhXhXhXhXhXxXhXhXxXxXhXhXhXhXhXhXhXxXhXhXxXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXxXhXhXxX", -"hXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXxXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXxXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXxXhXhXhXhXxXhXhXhXhXhXxXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXxXhXhXxXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXxXhXhXxXhXhXhXxXhXxXhXhXhXxXhXhXxXhXxXhXhXhXxXhXfXa.; X X X < a.fXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXxXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXxXxXhXhXxXxXhXhXxXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXxXhXhXhXhXhXhXxXhXhXxXxXhXxXhXhXxXhXhXhXhXhXhXhXxXhXhXxXhXhXhXxXhXxXhXhXhXhXhXhXhXhXxXxXhXhXxXhXhXhXhXhXhX", -"hXhXhXhXxXhXhXxXxXhXhXxXhXxXhXhXhXhXxXhXhXxXhXhXhXxXhXhXhXhXhXhXhXhXxXhXhXxXxXhXhXxXhXhXhXhXhXhXhXhXhXhXxXhXhXxXxXhXhXxXhXxXhXhXhXhXxXhXxXhXhXhXxXhXhXxXhXhXhXhXhXxXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXxXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXxXhXxXhXhXhXhXxXhXhXhXxXhXhXxXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXxXhXhXhXxXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXfXpXt.$ X X X X X ; t.pXxXhXhXhXxXxXhXhXxXhXhXhXhXhXxXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXxXhXhXxXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXxXhXhXxXxXhXhXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXxXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXxXhXxXhXhXxXhXhXhXhXhXhXxXhXhXhXxXhX", -"hXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXpXt.@ X X + t.gXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhX", -"hXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXxXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXpX` O X X X X X @ ` uXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhX", -"gXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXgXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXhXgXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXgXgXhXhXhXhXhXhXhXhXhXhXgXhXgXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXgXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXgXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXgXhXhXhXhXhXgXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXuX` X X X O ` uXgXgXhXhXhXhXgXhXgXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXgXhXgXhXhXhXhXhXhXhXhXgXgXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhX", -"hXhXhXhXhXgXhXgXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXgXhXhXhXhXhXhXgXhXgXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXgXhXhXhXhXhXhXhXgXhXhXhXhXhXhXgXhXhXhXhXhXhXgXhXgXhXhXgXhXgXhXhXhXhXhXhXhXhXhXgXhXgXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXgXhXgXhXhXhXhXhXhXhXhXgXhXhXhXgXhXhXhXgXhXhXhXhXhXhXgXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXgXhXhXgXgXhXhXuXJ X X X J uXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXgXhXhXgXhXhXhXgXhXhXhXhXhXhXgXhXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXgXhXgXhXhXgXhXhXhXhXhXhXhXgXhXgXhXhXhXgXhXhXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXhXhXhXhXgXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXgXhXhXhXgXhXhXhXhXhXhXhXhXgXhXgXhXhXgXhXgXhXhXgXhXhXhXhXhXhXhXgXhXgXhXgXhXgXhXhXhXhXhXhXhXhXhXhXgXhXhXhXgXhXhXgXhXhXhX", -"gXgXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXhXhXhXgXgXhXhXgXhXhXgXhXhXhXgXhXgXhXhXgXhXgXhXhXgXhXgXhXhXhXhXhXgXhXhXgXhXhXgXhXhXhXhXhXhXgXhXgXhXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXgXhXgXgXhXhXgXhXhXhXgXhXhXhXgXhXhXhXhXgXhXhXhXhXhXhXgXhXhXhXhXhXgXhXhXgXhXhXhXgXhXhXhXhXhXhXhXhXgXhXhXhXhXhXhXhXhXhXgXhXhXhXhXgXhXhXgXgXgXhXgXhXhXhXgXhXhXhXgXhXhXhXgXhXgXhXgXhXhXhXhXhXhXgXhXgXhXhXgXhXhXhXgXhXhXgXhXhXgXhXgXhXhXhXhXhXhXgXhXgXgXhXhXhXhXgXhXhXgXhXgXhXhXgXhXhXgXhXhXgXgXrXJ . X . J rXhXhXhXgXhXhXhXgXhXhXhXhXhXgXgXhXgXhXhXhXhXhXhXhXgXhXhXgXhXhXhXhXgXhXhXhXgXhXhXhXgXhXhXgXhXhXhXgXhXhXhXhXgXgXhXhXgXhXhXhXhXhXhXhXhXgXhXhXgXhXhXgXhXhXhXgXhXhXhXgXhXhXhXhXgXhXhXhXgXhXhXhXhXhXgXhXgXhXhXhXgXhXgXgXhXhXhXhXhXgXhXhXgXgXhXhXhXhXhXhXhXgXhXgXhXhXgXhXhXgXhXhXhXgXhXgXhXhXhXhXhXgXhXhXgXhXhXgXhXhXhXhXhXhXgXhXhXhXgXhXhXgXhXhXhXhXgXgXhXhXhXhXgXgXhXgXhXhXhXhXhXgXgXhXgXhXhXhXhXhXhXhXgXgXhXhXgXhXgXhXhXgXhXgXhXhXhXhXhXgXhXhXhXhXhXgXhXhXhXhXgXgXhXgXhXhXhXhXhXgXgX", -"hXhXhXgXgXhXgXhXgXhXhXgXhXgXgXgXhXgXgXhXgXhXgXhXhXhXgXhXhXhXhXgXhXgXgXhXhXhXgXgXgXhXhXhXgXhXhXhXgXhXhXgXhXhXgXhXgXhXgXhXhXgXhXgXhXgXhXgXgXhXgXhXgXhXhXgXhXgXgXgXhXgXhXgXhXgXgXhXgXhXhXhXhXhXhXgXhXhXgXhXhXhXgXgXhXgXgXhXgXhXgXhXgXgXhXgXhXhXgXhXgXhXgXhXhXgXgXhXgXhXhXgXgXhXgXhXgXhXhXgXhXgXgXgXhXgXgXhXgXhXgXhXhXhXgXhXhXhXhXgXhXhXgXhXhXhXgXhXhXgXgXhXgXhXhXhXhXgXhXgXgXhXgXhXgXhXhXgXhXhXgXhXhXgXgXhXhXgXhXgXhXgXhXgXgXhXgXhXgXhXhXhXhXgXhXgXgXgXhXhXhXgXhXhXgXhXhXgXgXgXhXhXgXrXV X X X m rXhXhXgXhXgXhXgXgXhXhXgXhXgXgXhXhXhXgXhXhXgXgXhXgXhXhXhXhXgXhXgXgXhXhXhXgXhXgXhXhXgXhXhXgXhXhXhXgXgXgXhXgXhXgXhXhXhXgXhXhXgXhXhXgXgXgXhXgXhXhXgXgXhXhXgXgXhXgXhXhXgXhXhXgXgXgXhXhXgXhXgXhXgXgXgXhXhXgXhXhXhXhXgXhXgXhXhXgXgXgXhXgXhXhXgXhXhXgXhXgXgXgXgXhXhXhXgXgXhXgXhXhXgXgXgXhXhXhXhXgXgXgXhXhXgXhXhXgXhXhXhXgXgXgXgXhXhXgXhXgXhXhXgXhXgXgXgXhXhXgXhXgXhXgXhXhXhXhXhXgXgXgXhXhXhXhXgXhXgXgXhXgXgXgXhXhXhXhXhXhXgXgXhXhXgXhXhXgXhXgXhXgXhXhXgXgXgXgXhXgXhXgXhXhXhXhXhXgXgXhXhXhXhX", -"gXhXgXhXhXgXgXhXhXgXgXhXhXgXhXhXgXgXhXhXgXhXgXgXgXgXhXgXgXhXgXhXgXhXhXgXgXhXgXhXhXhXgXgXhXhXgXgXhXgXgXhXhXgXgXhXhXgXhXgXgXhXhXgXgXhXgXgXhXgXgXhXhXgXgXhXhXgXgXhXgXgXhXhXgXgXhXhXhXgXhXgXgXhXhXgXhXgXgXhXgXhXgXhXgXhXgXgXhXhXgXgXgXhXgXhXhXgXgXhXhXgXgXhXgXhXhXgXgXhXgXhXhXgXgXhXhXgXgXhXhXgXhXgXgXgXhXhXgXhXgXgXgXgXhXgXhXhXhXhXhXgXgXhXgXgXhXgXgXgXhXhXhXhXgXgXgXhXgXgXhXgXgXhXhXgXgXhXhXgXgXhXgXhXhXgXgXhXhXgXgXhXgXgXhXgXgXhXhXhXgXgXgXhXhXhXhXgXhXgXgXhXgXgXgXhXgXhXhXgXhXgXgXfXgX'.V X X X V '.hXhXgXgXgXhXhXgXgXhXhXgXhXgXhXhXgXgXhXhXgXgXhXhXgXgXhXgXgXhXhXgXgXhXhXgXgXhXgXgXhXgXhXhXgXhXgXgXhXgXhXgXhXgXgXhXhXgXgXhXgXgXhXgXgXgXhXhXgXgXhXgXhXhXgXgXgXhXhXhXhXgXgXgXhXhXhXhXgXgXhXgXhXhXgXgXhXgXhXhXgXhXgXgXhXhXhXgXhXgXhXhXgXgXhXgXhXhXgXgXhXgXhXhXgXhXgXgXhXhXgXgXhXgXhXhXgXhXgXgXhXgXhXhXgXgXhXhXgXhXhXgXhXgXhXgXhXgXhXgXhXhXgXgXhXhXgXgXhXgXhXgXhXgXgXhXhXgXgXgXhXgXhXhXgXgXhXgXhXhXgXgXhXgXhXhXhXgXgXgXhXgXhXhXgXgXhXhXgXgXhXhXgXhXgXhXgXhXgXgXhXgXgXhXhXgXgXgXhXgXhXhXgXgXhX", -"hXgXgXgXgXhXgXgXgXhXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXhXgXgXhXgXgXhXhXgXgXhXgXgXhXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXhXgXgXgXhXgXhXgXgXhXhXgXgXhXgXhXgXgXgXhXgXgXgXgXhXgXgXhXgXgXhXgXgXgXhXgXgXgXhXgXgXhXgXgXhXgXgXgXhXgXhXgXgXhXgXgXgXhXgXgXgXgXgXgXhXgXgXhXgXgXhXgXgXhXhXgXgXgXgXgXhXgXgXhXgXgXgXgXgXhXgXhXgXgXhXgXgXhXgXhXgXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXgXgXhXhXgXgXhXgXhXgXgXgXhXgXgXgXgXhXgXgXgXhXgXhXgXgXgXhXgXgXhXgXhXgXgXgXgXgXhXgXgXgXgXhXgXgXhXgXgXgXhXgXhXgXhXhXgXgXhXgXfXgXgXgXC.b X b C.gXfXhXgXgXgXhXgXgXhXgXgXgXhXgXgXgXgXhXgXgXgXhXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXhXgXgXhXgXgXgXgXgXgXhXgXgXhXgXhXgXgXhXgXgXgXhXgXhXgXgXgXhXgXgXgXhXgXgXhXgXgXhXhXgXgXgXgXgXgXhXgXgXgXgXgXhXgXgXhXgXgXhXgXgXgXhXgXgXgXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXhXhXgXgXhXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXgXgXgXhXgXgXhXgXgXgXgXhXgXgXhXgXhXgXgXhXgXgXgXhXhXgXgXhXgXgXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXhXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXhXgXgXgXhXgXgXgXgXhXhXgXgXhXgXgXgXhXgXgXhXgXgXhXgXgX", -"gXgXhXgXgXgXgXhXgXhXgXgXhXgXhXgXgXhXgXhXhXgXgXgXgXhXgXgXhXgXhXgXgXhXgXhXgXgXhXgXgXhXgXhXhXgXhXgXgXhXhXgXhXgXhXgXhXgXgXgXgXhXgXgXgXgXhXgXgXgXgXhXgXgXhXgXhXgXhXgXgXhXgXhXhXgXgXgXgXgXhXgXgXgXhXgXgXgXhXhXgXgXhXgXhXgXhXgXhXgXgXgXgXhXhXgXgXgXhXgXhXgXgXgXgXhXgXgXgXgXhXgXgXgXgXhXgXgXhXgXgXhXhXgXgXhXgXhXhXgXgXgXgXhXgXgXhXgXhXgXgXgXhXgXhXgXgXhXhXgXhXgXgXgXgXgXgXgXhXgXgXgXgXhXgXhXgXhXgXgXhXgXhXgXgXhXgXhXgXgXgXgXhXhXgXgXhXgXhXgXhXgXgXgXgXgXgXgXhXgXgXgXgXhXhXgXgXgXgXhXgXgXgXgXgXhXgXgXgXC.h h C.gXgXgXgXgXgXhXgXhXhXgXgXgXgXgXgXgXhXgXgXgXgXhXgXhXgXhXgXgXhXgXgXhXgXhXhXgXhXgXgXhXgXgXhXgXhXgXgXhXgXhXgXgXhXgXgXhXhXgXhXgXgXgXgXgXhXgXgXgXhXgXgXgXgXgXgXhXgXgXgXhXgXhXgXhXhXgXgXhXgXgXhXgXhXgXgXhXgXhXgXgXhXgXgXhXgXhXhXgXhXgXhXgXhXgXgXhXgXhXgXhXgXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXhXgXgXhXgXgXgXhXgXgXgXhXhXgXhXgXgXgXgXgXgXhXhXgXgXgXhXgXhXgXhXgXhXhXgXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXhXgXgXgXhXgXhXgXgXhXgXgXhXgXhXhXgXhXgXgXhXhXgXhXgXhXgXgXgXgXgXgXhXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXhXgXgX", -"hXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXhXgXhXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXhXhXgXgXgXgXhXgXgXgXgXgXgXhXgXgXhXgXhXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXhXgXgXhXgXgXgXgXhXgXgXgXgXgXgXhXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXhXhXgXgXhXgXgXgXgXhXgXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXgXgXhXv.w i v.hXgXgXgXgXgXgXgXhXgXgXgXgXhXgXgXgXhXgXgXgXgXhXgXgXgXhXgXgXhXgXgXgXgXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXhXgXgXhXgXgXhXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXhXgXgXgXgXhXgXgXhXgXgXgXgXhXgXhXgXgXgXgXgXgXhXgXgXgXhXgXgXgXgXgXhXgXgXgXgXhXgXgXhXgXgXgXgXgXgXgXgXgXgXgXhXgXgXhXgXhXgXgXgXgXgXgXgXhXgXgXhXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXhXgXgXhXgXhXgXgXgXgXgXgXgXhXgXgXhXgX", -"gXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXv.9 9 v.gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", -"gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXc.6 X 5 c.dXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", -"gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXhXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXa.5 X 5 a.aXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", -"gXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXdXgXgXgXgXgXdXgXgXgXgXdXgXgXdXgXgXdXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXdXgXgXgXgXgXgXdXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXdXdXpXy.; $ y.fXdXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXdXgXgXgXgXgXgXgXgXdXdXgXgXgXgXgXgXgXgXdXgXgXgXgXdXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXdXdXgXgXgXgXgXgXgX", -"gXdXgXgXgXgXgXdXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXdXgXdXgXgXgXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXdXgXgXdXgXgXgXdXgXdXgXgXdXdXgXdXgXgXgXdXgXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXdXgXdXdXgXgXdXdXgXdXgXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXdXgXgXgXgXgXdXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXdXdXgXgXdXgXdXdXgXgXgXdXgXdXgXgXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXdXdXgXgXdXgXdXgXgXgXdXgXdXgXgXgXgXdXgXgXdXgXgXdXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXdXgXgXdXgXdXgXgXdXgXsXt.$ ; y.pXgXgXdXgXgXdXgXdXdXgXgXdXgXdXdXgXgXdXdXgXgXgXgXgXdXgXgXdXgXgXdXgXgXdXgXdXdXgXdXgXgXdXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXdXdXgXdXgXgXdXdXgXdXgXgXgXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXgXgXdXdXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXdXgXdXgXdXgXgXdXgXgXgXgXdXgXdXgXgXgXgXdXdXgXgXgXdXdXgXgXgXgXgXdXgXgXdXgXdXgXdXgXgXgXgXdXdXdXgXgXgXgXgXdXgXgXgXdXgXdXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXdXgXgXgXdXgXgXdXgXgXdXgXgXdXgXgXgXgXgXdXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXdXgXgXgXgXgXdXgXgXgXdXgX", -"dXgXdXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXdXgXdXdXgXdXgXdXgXgXdXgXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXdXgXdXdXgXgXdXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXgXgXdXgXgXgXdXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXdXgXdXdXgXdXgXdXgXgXgXdXgXdXgXgXgXdXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXgXdXgXdXgXgXdXgXdXgXgXgXdXgXdXgXgXdXdXgXdXdXgXgXdXgXdXgXgXdXgXdXgXgXgXdXgXdXgXdXdXgXgXdXgXdXgXgXdXgXgXdXdXgXdXgXdXgXgXgXdXgXdXdXdXpXt.@ @ $.aXdXgXgXdXgXdXgXdXgXgXgXdXgXdXgXgXgXdXgXdXgXgXdXgXgXdXgXgXdXgXdXgXgXgXdXgXdXdXgXgXdXgXgXdXgXgXdXgXdXgXdXdXgXgXdXgXdXdXgXdXgXdXgXgXdXgXgXdXgXgXdXgXdXgXgXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXdXgXdXdXgXdXdXgXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXdXgXdXgXgXdXdXgXgXdXdXgXdXgXdXgXgXdXdXgXgXgXdXgXdXgXgXdXdXgXgXdXgXdXdXgXdXgXdXgXgXdXdXgXgXgXgXdXdXgXdXgXgXdXdXgXgXdXgXdXdXgXdXdXgXdXgXgXdXdXgXdXgXgXdXdXgXdXgXdXgXgXdXgXdXgXgXgXdXgXdXgXdXdXgXgXdXgXdXdXgXdXdXgXdXdXgXdXdXgXdXdXgXdXgXgXdXdXgXdXgXgXdXdXgXdX", -"gXdXgXgXgXdXgXdXgXdXgXgXdXgXdXgXgXdXgXgXgXdXgXdXgXgXdXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXgXdXgXdXgXgXdXgXdXgXgXgXgXdXgXdXgXgXgXdXgXdXgXdXgXgXgXgXdXgXdXgXdXgXdXgXgXdXgXdXgXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXdXgXgXgXgXdXgXgXgXdXgXdXgXdXgXgXdXgXdXgXgXdXgXgXgXdXgXdXgXgXdXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXgXdXgXgXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXgXgXgXdXdXgXgXgXgXdXgXdXgXdXdXgXgXdXuXJ J uXgXgXdXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXdXgXdXgXgXgXgXdXgXgXgXgXdXgXdXgXdXgXgXdXgXdXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXgXdXgXgXgXdXgXdXgXgXdXgXgXdXgXgXdXgXdXgXdXdXdXgXgXgXdXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXgXgXgXdXgXdXgXdXgXgXgXdXgXdXgXdXgXgXgXgXgXdXgXdXgXgXgXgXgXdXgXdXgXgXdXgXdXgXgXgXgXgXdXgXdXgXgXgXgXdXgXgXdXgXdXgXgXdXgXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXgXgXdXgXdXgXgXgXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXgXdXgXgXgXdXgXdXgXgXdXgX", -"dXgXdXdXgXdXdXgXdXgXdXgXdXgXgXdXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXdXdXdXgXdXgXdXgXdXdXgXdXdXgXdXgXdXgXdXgXgXdXdXgXdXgXdXdXdXgXgXdXgXdXdXgXgXdXgXdXgXdXdXdXdXgXdXgXdXgXdXgXdXgXgXdXgXdXdXgXdXgXdXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXgXgXdXdXdXdXgXdXdXgXdXdXgXdXgXdXgXdXgXgXdXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXgXdXgXdXdXgXdXgXdXgXgXdXdXgXdXgXdXgXdXgXgXdXdXgXgXdXgXdXgXdXdXdXdXdXgXdXgXdXgXdXgXdXdXgXdXgXdXgXdXgXdXdXgXgXgXdXgXdXdXgXgXdXgXdXgXdXdXdXdXgXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXdXdXdXdXgXgXdXdXdXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXdXgXdXgXdXgXdXgXgXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXdXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXgXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXgXgXdXgXgXdXdXgXgXdXgXdXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXdXgXdXgXdXgXgXdXdXgXdXgXdXgXgXdXdXdXdXgXdXgXgXdXdXdXdXgXdXgXgXdXgXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXgXdXgXdXgXdXgXgXdXdXgXdXgXdXgXdXgXgXdXgXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXdXgXgXdXgXdXgXdXgXdXgXdXgXdXdXgXdXgXgXdXdXdXdXgXdXgXdXgXdXdX", -"dXgXgXdXgXdXgXdXdXdXdXdXdXdXdXdXdXgXgXdXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXdXgXdXdXdXdXgXdXdXdXgXdXdXdXgXgXdXgXdXgXdXdXdXdXdXdXdXdXdXgXdXdXgXgXdXgXdXgXdXdXdXdXdXdXgXdXgXdXgXgXdXdXgXgXdXgXdXdXdXgXdXdXdXdXdXgXdXdXgXgXdXgXgXgXdXdXdXdXgXdXgXdXgXdXgXdXgXdXgXdXgXdXdXdXgXgXdXgXdXgXdXdXdXgXdXdXdXdXdXdXgXgXdXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXdXdXdXdXdXdXgXdXdXdXgXdXdXdXgXgXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXgXdXgXdXdXdXgXdXgXdXdXdXgXdXgXdXgXdXgXgXdXdXgXgXdXgXdXgXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXdXgXdXdXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXdXdXdXdXgXdXgXdXdXdXdXdXdXdXgXgXdXgXdXdXdXgXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXdXdXdXdXgXdXdXdXdXdXdXgXdXgXdXdXdXdXdXdXgXdXdXdXgXdXgXdXgXdXgXdXgXgXdXdXdXdXdXdXdXgXdXgXdXdXgXgXdXgXdXgXdXdXdXdXdXdXgXdXgXdXgXdXgXdXgXgXdXgXdXgXdXgXdXdXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXgXdXgXdXdXdXdXgXdXgXdXdXgXdXgXgXdXgXdXdXgXdXgXgXdXgXdXdXgXgXdXgXdXgXdXdXgXgXdXdXgXdXgXdXgXgXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXgXgXdXgXdXgXdXgXdXgXdXdXdXdXdXdXgXdXdXdXgXdXgXdXgXdXgXdXgXgXdXdXdXdXdXdXdXgXdX", -"dXdXdXdXdXdXdXdXgXdXgXdXdXgXdXdXdXdXdXdXdXgXgXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXgXdXgXdXdXdXgXdXdXdXdXdXdXdXdXgXdXgXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXgXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXgXdXgXdXgXdXdXdXdXdXdXdXdXdXdXgXdXgXdXdXgXdXgXdXdXdXgXdXdXdXdXdXdXdXdXdXgXgXdXdXgXdXdXgXdXdXdXdXdXdXdXgXgXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXgXgXdXgXdXgXgXgXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXgXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXgXdXdXdXdXdXdXgXdXgXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXgXgXdXgXdXgXdXdXdXdXgXgXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXgXdXdXgXdXgXdXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXgXdXdXgXdXdXdXdXgXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXgXgXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXgXgXdXdXgXdXdX", -"dXgXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXgXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXgXdXdXdXdXgXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXgXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXdXdXgXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXgXdXdXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXgXdXgXdXdXdXdXdXgXdXdXdXdXdXdXdXgXdXgXdXdXgXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXgXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXgXdXdXgXdXdXdXdXdXdXdXgXdXdXdX", -"dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXaXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX", -"dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXgXdXdXdXdXdXdX", -"dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXsXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXsXdXdXdXdXdXdXsXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdXdXsXdXdXdXdXdXsXdXdXdXdXdXdXdXdXsXdXdXdXdXdXdXdXdXdXdXdXdX", -"dXdXdXsXdXsXsXdXdXdXsXdXdXdXdXsXsXdXdXdXdXsXdXdXdXsXsXdXsXdXdXdXdXsXdXdXdXdXsXsXdXsXdXdXdXdXdXsXdXdXdXsXdXsXdXsXdXdXsXdXdXdXdXsXdXdXdXdXsXdXsXdXdXdXdXsXdXsXsXdXsXdXsXdXsXdXdXdXsXdXsXdXsXdXdXdXdXsXsXdXsXdXdXdXdXdXsXsXdXdXdXdXdXsXdXdXdXsXdXsXsXdXsXdXdXdXdXdXdXdXdXsXdXsXsXdXdXdXsXdXdXdXdXsXsXdXdXdXdXsXdXdXdXsXsXdXsXdXdXdXdXsXdXdXdXdXsXsXdXsXdXdXdXdXdXsXdXdXdXsXdXsXdXsXdXdXsXdXdXdXsXdXdXdXsXsXdXdXsXdXdXsXsXdXsXdXdXdXdXdXsXdXsXdXdXdXdXdXsXdXsXdXdXdXsXdXsXdXdXdXdXdXdXdXdXdXsXsXdXdXsXdXdXdXdXsXdXdXaXdXdXdXdXdXdXsXdXsXdXdXdXdXsXdXsXsXsXdXdXdXsXdXdXdXdXsXdXsXsXdXdXdXsXdXdXdXdXsXdXdXsXsXdXdXdXdXdXdXdXdXdXdXdXsXdXsXdXdXdXdXsXdXsXsXdXdXdXdXsXsXdXsXdXdXdXdXsXsXdXdXdXdXdXdXsXsXdXdXdXdXdXsXdXsXdXdXdXsXdXdXsXdXdXsXdXsXdXdXsXdXaXdXdXsXdXsXsXdXdXdXsXdXsXdXdXdXdXdXsXdXsXdXdXdXdXdXsXdXdXdXdXsXdXdXdXdXsXdXdXsXsXdXdXsXdXdXdXsXdXsXdXsXdXdXsXdXdXsXdXdXsXsXdXdXdXsXdXdXdXdXdXdXdXsXdXdXsXsXdXdXdXsXdXsXdXdXsXdXdXdXdXdXdXsXdXsXdXdXsXdXdXdXsXdXsXdXdXdXsXdXdXdXdXsXsXdXsXdXdXdXdXsXdXdXdXdXsXsXdXsXdXdXdXdXsXsXdXdXdXdXdXsXdXsXdXdXsXdXdXsXdXsX", -"sXsXdXdXdXdXdXdXdXsXdXdXsXdXdXdXdXdXsXdXdXdXsXsXdXdXdXdXdXdXsXdXdXdXdXsXsXdXdXdXdXdXdXsXsXdXdXdXsXsXdXdXdXdXdXdXdXsXdXdXsXdXdXdXsXdXsXdXsXdXdXdXdXsXdXdXdXdXdXdXdXdXsXdXdXdXsXdXdXdXsXdXdXdXsXdXdXdXdXdXdXdXsXdXsXdXdXdXdXsXdXsXdXdXdXsXdXdXdXdXdXdXdXdXsXdXsXsXsXsXdXdXdXdXdXdXdXsXdXdXsXdXdXdXdXdXsXdXdXdXsXsXdXdXdXdXdXdXsXdXdXdXdXsXsXdXdXdXdXdXdXsXdXsXdXdXsXsXdXdXdXdXdXdXdXsXdXdXsXdXdXdXdXsXdXdXdXsXdXdXdXdXdXdXdXdXsXdXsXdXdXdXdXdXdXsXsXdXdXdXdXdXdXsXdXdXdXdXsXdXsXdXsXdXdXsXdXdXdXsXdXdXsXdXdXdXdXsXsXdXsXdXsXsXdXdXdXdXdXsXsXdXdXdXdXdXsXdXsXdXdXdXdXsXdXdXdXdXdXdXsXdXdXdXdXsXdXdXdXsXdXdXdXsXsXdXsXsXdXsXdXsXdXdXdXdXdXsXsXdXdXdXdXdXdXsXsXdXdXdXdXdXdXsXdXsXdXdXdXsXdXsXdXsXdXdXsXsXdXsXdXdXdXdXdXdXsXdXsXdXdXdXdXdXdXdXdXsXdXdXsXsXdXdXdXdXdXdXsXdXsXdXdXdXsXdXsXdXsXdXdXdXsXdXdXsXdXdXsXdXdXdXsXdXsXdXdXdXdXsXsXdXdXdXdXsXdXdXdXsXdXdXdXsXdXdXdXdXdXsXdXdXdXsXdXdXdXsXdXsXsXdXdXdXsXdXdXdXsXdXdXsXdXdXdXsXdXdXsXsXdXsXdXdXdXdXdXsXdXdXsXdXdXdXdXdXsXdXsXdXdXsXdXdXdXdXdXdXdXdXdXdXdXsXsXdXdXdXdXdXdXdXdXdXdXdXsXsXdXsXdXsXdXdXdXsXdXdXsXdXdXdX", -"dXsXdXdXsXdXsXdXdXdXdXdXsXdXsXdXdXsXdXdXsXdXsXdXsXdXsXdXdXdXdXsXdXdXdXsXsXdXsXsXdXdXdXsXdXdXsXdXdXsXsXdXsXsXsXdXdXdXdXdXsXdXsXsXsXdXsXdXdXsXdXsXsXdXsXdXsXdXdXsXdXsXdXsXsXdXdXdXdXsXdXsXsXdXsXdXsXdXsXdXsXdXsXsXdXsXdXsXdXdXsXdXdXsXdXsXsXdXsXsXsXdXdXsXdXsXdXdXdXdXdXdXsXdXsXdXdXdXdXdXsXdXsXdXdXsXdXdXsXdXsXdXsXdXsXdXdXdXdXsXdXdXdXsXdXdXsXsXdXdXdXdXdXdXsXdXdXsXsXdXsXsXsXdXdXdXdXdXsXdXsXsXdXdXsXdXdXdXdXsXsXaXsXdXdXsXdXsXsXdXsXdXdXsXdXdXsXdXsXdXdXsXdXdXsXdXdXsXdXsXdXsXdXdXsXdXdXdXdXsXdXsXdXdXsXdXsXdXsXdXdXsXdXdXdXdXdXdXdXsXsXdXsXdXdXdXdXsXsXdXsXdXsXdXsXdXsXdXsXdXdXdXdXsXsXdXsXdXdXdXsXdXaXdXsXdXdXsXdXdXsXdXsXdXdXdXdXsXsXdXsXdXdXdXdXsXdXdXsXdXdXdXsXdXdXdXsXdXdXdXsXdXdXdXsXdXdXsXdXdXsXdXdXsXsXdXdXdXsXdXsXdXdXsXdXsXsXdXdXdXdXsXsXdXsXdXdXsXdXsXdXsXsXdXdXdXdXsXdXsXsXdXdXdXdXdXdXdXsXdXsXdXsXdXsXdXsXsXdXdXdXsXdXsXsXdXsXdXdXdXdXsXdXdXdXdXsXdXsXdXdXdXdXsXdXsXdXsXsXdXsXdXsXdXsXdXdXsXdXsXdXdXdXsXdXdXdXdXdXsXdXdXsXdXsXdXdXdXdXdXsXdXsXdXsXdXdXdXsXdXsXdXsXdXsXdXsXdXdXsXdXdXdXsXdXdXsXdXdXdXsXdXdXdXsXdXdXsXdXdXsXdXsXdXsXdXdXdXsXdXsXdX", -"sXdXsXsXdXsXdXsXsXsXsXsXdXdXsXsXdXsXdXsXsXdXdXsXdXsXdXsXdXsXsXdXsXsXdXsXdXsXdXdXdXsXdXsXsXsXdXdXsXdXdXsXsXdXdXsXsXsXsXsXdXsXsXdXdXsXdXsXsXdXsXaXsXsXdXsXdXsXdXsXsXdXsXdXdXsXsXsXsXdXsXdXdXsXdXsXdXsXdXsXdXsXdXsXsXdXsXdXsXsXdXsXsXdXsXdXdXsXaXsXdXsXsXdXsXdXsXdXsXsXsXsXdXsXdXsXsXsXsXsXdXsXdXsXdXsXdXsXsXdXsXdXdXsXdXsXdXsXsXdXsXsXdXsXsXsXdXdXsXsXdXsXsXsXdXdXsXdXdXsXsXdXdXsXsXsXsXsXdXsXsXdXsXdXsXdXsXsXsXdXsXsXdXsXdXsXsXdXsXdXsXsXsXdXsXsXsXdXsXsXdXsXsXsXdXsXdXsXsXdXsXdXsXsXsXdXsXsXsXdXdXsXsXsXsXdXsXdXdXsXsXdXsXsXsXdXsXsXsXdXdXsXdXdXsXsXsXdXsXdXsXdXsXsXdXsXdXsXdXsXsXsXsXdXdXsXdXsXsXdXsXdXsXsXdXsXsXdXsXdXsXsXdXsXsXsXsXdXdXsXdXdXsXsXsXdXsXsXdXdXsXsXdXsXsXdXsXdXsXsXdXsXsXdXsXdXsXdXsXdXsXsXsXsXdXsXsXsXsXdXsXsXsXdXsXdXdXsXsXsXsXdXdXsXdXsXdXsXsXdXsXdXdXsXsXsXsXdXsXdXdXsXsXsXsXsXsXsXdXsXdXsXdXsXdXsXsXdXsXdXsXdXsXdXdXsXdXsXsXdXsXdXsXsXsXsXsXdXsXdXsXsXsXdXsXdXsXdXdXsXdXsXdXsXdXsXsXdXsXdXsXdXsXdXsXsXsXsXsXdXsXdXsXsXdXsXsXsXsXsXsXdXsXsXdXsXsXsXdXsXdXsXdXsXdXsXdXsXsXdXsXsXdXsXsXsXdXdXsXsXdXsXsXdXsXdXsXdXsXdXsXsXdXsXdXsXsXsXsXdXsXsX", -"sXsXdXsXsXsXdXdXsXdXdXsXsXdXsXsXsXdXsXdXsXdXdXsXsXdXsXsXsXdXsXsXsXdXsXdXsXsXsXsXsXsXsXdXsXsXsXsXdXsXdXsXsXsXdXdXsXdXdXsXsXdXsXsXsXsXdXdXsXdXdXsXdXdXsXsXsXdXsXdXsXdXdXsXsXdXsXdXsXdXdXsXsXdXsXdXsXdXsXsXsXdXsXsXsXsXsXdXsXsXsXdXsXdXsXsXsXsXsXdXsXsXsXdXdXsXsXsXdXdXsXsXsXsXdXdXsXdXdXsXsXdXsXsXsXsXdXdXsXdXdXsXsXdXsXsXsXdXsXsXsXdXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXdXsXsXsXdXdXsXdXdXsXsXdXsXsXdXsXsXsXdXsXsXsXsXsXdXsXsXdXsXsXdXsXdXsXsXdXdXsXdXsXdXsXsXdXdXsXsXsXsXdXdXsXsXsXdXsXsXsXsXsXdXsXsXsXdXdXsXdXdXsXsXdXsXsXdXsXsXsXsXdXsXdXsXsXsXsXsXdXsXdXsXsXsXsXdXdXsXsXsXsXdXdXsXdXdXsXsXdXsXsXdXsXsXsXdXsXsXsXsXsXdXsXsXsXdXdXsXdXsXdXsXsXsXsXsXdXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXdXsXsXsXdXdXsXdXdXsXdXdXsXsXdXsXsXsXsXsXsXsXsXsXdXsXsXdXsXsXdXsXdXsXsXdXsXdXdXsXdXsXsXdXsXdXsXdXdXsXsXdXsXsXsXsXdXdXsXdXdXsXsXsXsXdXsXsXsXdXdXsXsXsXdXsXsXsXdXsXsXsXsXsXdXsXsXdXsXsXsXsXsXdXdXsXsXsXsXsXdXsXdXsXsXsXdXsXsXsXsXsXdXsXsXsXdXdXsXdXdXsXdXdXsXsXsXsXdXdXsXdXdXsXsXdXsXsXsXdXsXsXsXsXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXdXsXsXsXdXdXdXsXsXsXdXdXsXsX", -"dXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXdXsXdXsXdXsXsXsXdXsXdXdXsXsXdXsXsXsXdXdXsXsXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXdXsXsXsXsXsXsXdXsXsXsXdXsXdXsXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXsXdXsXsXsXdXsXdXsXdXdXdXsXsXsXdXsXsXsXdXsXdXdXdXsXsXsXdXsXsXsXsXdXsXsXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXdXsXsXsXsXsXsXsXsXsXdXsXdXsXdXsXsXsXdXsXdXdXsXsXdXsXsXsXdXdXsXdXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXsXdXsXsXsXdXdXdXsXdXsXsXdXsXdXdXsXsXsXsXsXsXdXdXsXsXsXsXsXsXdXsXdXsXsXsXdXdXsXsXsXdXdXdXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXsXdXsXsXsXsXdXsXdXdXsXsXsXsXdXsXdXdXsXsXsXsXdXdXsXsXsXsXsXsXsXsXsXsXdXsXsXdXsXsXsXdXdXdXsXdXsXdXsXsXsXsXsXsXdXsXdXdXsXsXsXsXdXsXdXdXsXsXdXsXdXsXdXdXsXsXdXsXdXsXdXdXsXdXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXdXsXdXdXsXdXdXdXsXsXsXsXdXsXdXdXsXsXsXsXsXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXdXdXsXsXsXsXsXsXsXdXdXsXsXsXdXsXsXsXdXdXsXsXsXdXdXsXsXdXdXdXsXdXsXsXdXsXdXdXdXsXsXsXsXdXdXdXsXdXsXsXdXdXsXsXsXdXdXdXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXdXsXsXsXsXsXsXsXsXsXsXdXsXdXsXdXsXdXsXdXsXdXdXsXsXdXsXdXdXsXdXsXdXsXdXsXdXsXsXsXsXsXdXdXsXsXsXdX", -"sXdXsXsXdXsXsXsXsXdXsXdXsXdXsXsXsXsXsXsXdXsXdXsXsXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXsXdXsXsXsXsXdXsXsXdXsXsXdXsXsXsXsXdXsXdXsXdXsXdXdXsXsXsXsXdXsXsXsXdXsXsXsXsXsXsXdXsXsXdXsXdXsXsXdXsXsXsXsXdXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXsXsXdXsXsXdXsXsXsXdXsXsXsXsXdXsXdXsXsXsXdXsXsXdXsXsXsXsXdXsXdXsXsXsXsXsXsXsXsXdXsXsXdXsXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXsXdXsXsXsXsXdXsXsXdXsXsXdXsXsXsXsXdXsXdXsXdXsXdXsXdXsXdXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXdXdXsXsXsXsXsXsXdXdXsXsXsXsXsXsXdXsXsXsXdXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXdXsXsXsXsXdXsXsXsXsXdXsXsXsXsXdXsXsXdXsXsXsXsXsXsXsXdXsXsXsXsXsXsXdXsXdXsXsXsXsXsXsXdXsXdXsXsXsXsXdXsXsXsXdXsXsXsXsXdXsXsXsXsXdXsXsXdXsXsXsXsXdXsXsXdXsXsXsXsXdXsXsXdXsXsXsXsXdXsXdXsXsXsXdXsXsXsXsXdXsXdXsXdXsXsXsXsXsXdXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXdXsXdXsXsXdXsXsXdXsXdXsXsXdXsXsXdXsXsXsXsXdXsXsXsXsXdXsXdXsXsXdXsXsXsXsXdXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXdXsXsXsXsXsXdXsXsXsXsXsXsXdXsXsXsXsXdXsXsXsXdXsXsXsXsXdXsXdXsXdXsXsXdXsXsXsXsXdXsXdXsXdXsXsXsXsXsXsXsXdXsXsXsXsXdXsXsXdXsXsXsXsXsXsXdXsXsXsXdXsXsXsXsXdXsXsXsXdXsXsX", -"sXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXdXsXsXsXsXsXdXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXdX=XdXsXsXsXsXsX", -"=XsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsX=XsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX", -"sXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XdXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsX", -"sXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsX=XsXsXsXsXsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsX=XsX=XsX=XsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsX=XsX=XsXsXsXsXsX=XsXsX=XsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsX=XsXsXsXsXsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsX=XsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsX=XsXsXsX=X=XsXsX=XsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=X=XsXsXsXsXsXsXsXsXsXsX=X=XsXsXsXsXsXsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsX=XsX=XsX=XsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=XsXsX=XsXsXsXsXsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsXsXsXsXsXsXsXsXsXsX=X", -"sX=XsX=XsX=XsXsXsX=XsXsXsX=XsX=X=XsX=XsXsX=XsXsXsXsX=XsX=XsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsX=XsXsXsX=XsX=XsX=XsXsX=XsXsXsXsXsXsXsX=XsXsX=XsX=XsX=XsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsXsX=XsXsX=XsX=XsX=XsX=XsXsXsX=XsX=XsX=XsXsXsXsX=XsX=XsX=XsXsX=XsX=XsX=XsXsXsX=XsXsXsX=XsX=X=XsX=XsXsXsX=XsXsXsX=XsX=XsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsX=XsXsXsX=XsX=XsX=XsXsXsXsX=XsX=XsX=XsX=XsX=XsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsXsX=XsX=XsX=XsX=XsXsXsXsXsX=XsXsXsXsXsXsXsXsX=XsX=XsXsXsX=XsX=XsXsX=XsXsX=X=XsXsXsX=XsXsX=X=XsX=XsXsX=XsX=XsX=XsX=XsXsXsXsXsX=XsX=XsX=XsX=XsXsXsXsXsX=XsXsX=XsX=XsXsX=XsXsX=XsX=XsXsX=XsXsX=XsX=XsXsX=XsXsX=XsX=XsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsX=XsX=XsX=XsXsX=XsXsXsXsXsXsXsX=XsXsX=XsX=XsX=XsX=XsXsXsX=XsXsXsX=XsXsXsX=XsXsX=XsXsX=XsX=XsXsXsX=XsX=XsXsXsX=XsX=XsXsXsX=XsX=XsX=XsXsXsXsX=XsXsXsX=XsX=XsX=XsX=XsX=XsX=XsX=XsXsX=XsXsXsX=XsX=XsX=XsXsXsXsX=XsXsX=XsX=XsX=XsXsXsX=XsXsXsX=XsX=X=XsX=XsXsXsX=XsXsXsX=XsX=XsX=XsX=XsXsX=XsXsX=XsX=XsXsX=XsXsX=XsXsXsXsX=XsX=XsXsXsX=XsX=XsX=XsXsX", -"sX=XsX=X=XsXsX=XsX=XsX=XsXsX=XsXsX=X=XsX=XsX=XsX=XsX=XsX=XsXsX=X=XsX=XsXsXsX=XsX=XsX=XsXsXsX=XsXsX=X=XsX=XsXsX=XsX=XsX=X=XsXsX=XsX=XsXsXsX=XsXsXsX=X=XsX=XsXsXsX=XsXsX=X=XsX=X=X=XsXsX=X=XsX=X=X=XsXsX=XsX=XsX=XsX=XsXsXsX=X=XsXsX=XsXsX=XsXsX=X=XsX=X=X=XsXsX=XsX=XsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=X=XsX=XsX=XsX=XsX=XsX=XsXsX=X=XsX=XsXsXsX=XsX=XsX=XsXsXsX=XsX=XsXsXsX=XsXsX=XsX=XsX=X=XsXsX=X=XsX=XsX=XsXsX=XsX=X=XsXsX=X=XsX=X=XsX=X=XsXsX=X=X=XsX=X=XsXsX=XsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsX=XsXsX=X=X=XsX=XsX=XsX=XsXsX=XsX=XsX=XsXsXsX=XsX=XsX=XsXsXsX=XsXsX=X=XsX=XsXsXsX=XsXsX=X=X=XsX=XsX=XsXsXsXsX=XsX=XsXsXsX=XsXsX=XsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsX=XsXsXsX=XsXsX=XsX=XsXsX=XsX=XsXsX=XsXsXsX=XsXsXsX=X=XsX=XsXsXsX=XsXsX=X=XsX=X=X=XsXsX=X=XsX=X=XsX=X=XsX=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=XsXsX=XsX=XsXsX=XsXsXsX=X=XsXsX=XsX=X=XsXsXsX=XsXsXsX=XsX=XsXsX=XsXsX=XsX=XsXsX=XsXsXsX=XsX=XsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=X=XsX=XsX=XsX=XsX=XsX=XsXsX=XsXsX=XsXsX=XsXsXsXsX=XsXsX=XsXsX=XsXsXsX=XsXsX=XsX=XsXsX=XsXsX=X", -"sXsX=XsXsX=X=XsXsX=X=XsX=X=XsXsX=XsXsX=XsX=X=XsXsXsXsX=XsXsX=XsXsX=XsX=X=XsXsX=XsX=XsX=X=XsXsX=X=XsXsXsXsX=X=XsXsXsX=XsXsX=X=XsX=XsXsX=X=XsX=X=X=XsXsXsX=XsX=XsXsX=X=XsXsXsXsXsXsX=X=XsXsXsXsXsXsX=XsXsX=XsXsXsX=XsX=XsX=XsXsX=XsXsX=X=XsX=X=XsXsXsXsXsXsX=XsXsXsXsX=XsXsX=X=XsXsX=X=XsXsX=XsXsX=XsXsX=XsX=XsX=XsXsXsX=XsXsX=XsXsX=XsX=X=XsXsX=XsX=XsX=X=XsXsX=X=XsX=XsXsX=X=XsXsXsX=XsXsX=X=XsXsXsXsX=XsXsX=XsXsXsXsX=X=XsXsXsXsXsXsXsXsX=X=XsXsXsXsXsXsX=X=XsX=X=XsXsX=XsXsX=X=XsXsX=XsXsX=X=XsXsX=XsXsXsX=XsXsX=X=XsX=X=XsXsXsX=X=XsX=XsXsX=XsX=X=XsX=XsXsX=X=XsXsXsX=XsX=XsXsXsX=XsXsXsX=XsXsX=X=XsX=X=XsXsX=XsX=XsXsX=X=XsX=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=X=XsXsXsX=X=XsX=X=XsX=XsXsX=X=XsX=X=X=XsXsXsX=XsX=XsXsX=X=XsXsXsXsXsXsX=X=XsXsXsXsXsX=XsXsXsXsX=X=XsXsXsX=XsXsX=X=XsXsX=X=XsX=X=XsXsXsX=X=XsXsX=XsX=XsX=XsX=X=XsXsXsX=X=XsXsX=XsXsX=XsX=X=XsX=X=XsXsXsX=X=XsXsX=XsX=XsXsX=XsXsX=X=XsXsX=X=XsXsX=XsXsX=XsXsX=XsX=XsX=XsXsXsX=XsXsX=XsX=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=X=XsXsXsX=X=XsX=X=XsX", -"=X=X=XsX=XsXsX=X=XsXsX=X=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsXsX=X=X=X=XsXsX=X=X=XsX=XsXsX=XsX=X=XsXsX=X=XsXsXsX=X=X=XsX=X=XsX=XsX=XsX=X=XsXsX=XsX=XsX=X=XsX=XsXsX=X=XsX=X=X=XsXsX=XsX=X=XsX=X=X=XsXsX=XsX=XsX=XsX=X=XsXsX=X=X=X=XsX=XsXsX=X=XsXsX=X=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsX=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsXsX=X=X=X=XsXsX=X=X=XsX=XsXsX=XsX=X=XsX=X=X=XsX=XsX=XsXsXsX=X=X=XsX=X=X=XsXsX=X=XsX=X=X=XsXsX=X=XsXsX=X=XsX=XsXsX=X=XsX=X=X=XsX=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsXsX=X=X=XsX=X=X=XsXsX=X=XsXsX=X=XsXsX=XsX=XsX=X=XsX=X=X=X=XsXsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsX=XsX=X=X=X=XsXsX=X=X=XsXsX=XsX=XsX=X=XsXsX=X=XsXsXsX=X=X=XsX=X=X=XsXsX=XsX=XsX=X=XsXsX=XsX=XsX=XsXsX=X=X=X=XsXsX=X=X=XsX=XsXsX=X=XsXsX=X=XsXsX=X=X=XsXsX=X=XsXsX=X=XsXsXsXsX=X=X=XsXsX=XsXsX=XsX=XsXsX=X=XsXsX=X=X=XsXsX=X=XsXsX=X=X=XsX=XsXsX=X=XsXsX=X=XsXsX=XsX=X=XsXsX=X=XsXsX=X=XsX=X=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsX=X=XsXsXsX=X=X=X=XsXsX=X=X=XsXsX=XsX=X", -"=XsX=XsX=X=XsX=XsX=X=XsX=X=X=X=XsX=XsX=X=XsX=X=X=X=XsX=X=X=X=XsX=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=X=X=XsXsX=X=X=X=XsX=XsX=X=XsX=X=XsX=X=XsX=XsX=X=X=X=XsXsX=X=XsX=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=X=XsX=X=X=XsXsX=X=X=XsX=XsX=X=XsXsX=X=X=XsX=X=X=X=XsX=X=X=XsX=XsX=XsX=X=XsX=XsX=X=XsX=X=X=X=XsX=XsX=X=XsX=X=X=X=XsX=X=X=X=XsX=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=X=X=XsXsX=X=X=X=XsX=XsX=X=XsX=X=X=XsX=X=XsX=XsX=X=XsX=X=X=X=XsX=X=X=XsXsX=X=XsX=X=X=XsXsX=X=XsX=X=X=X=XsX=X=X=X=XsX=X=X=XsXsX=X=X=X=XsX=X=XsX=XsX=X=XsX=X=X=X=X=XsX=X=X=X=XsX=X=XsX=X=X=X=XsX=X=X=X=XsXsX=X=XsX=X=X=XsX=X=XsX=XsX=X=X=XsX=X=X=XsX=X=XsX=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=XsX=X=XsX=XsX=X=X=XsXsX=X=X=XsX=X=XsX=X=X=XsXsX=X=X=XsX=XsX=X=XsX=X=XsX=X=X=X=XsX=X=XsX=X=X=X=XsX=X=X=XsXsX=X=X=X=XsX=XsX=X=XsX=XsX=X=XsX=X=X=X=XsX=X=X=X=XsX=X=X=XsX=X=X=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=X=X=X=XsX=X=X=XsXsX=X=X=XsX=XsX=X=XsX=X=X=X=XsX=XsX=X=XsX=X=X=X=XsX=X=XsX=XsX=XsX=X=X=XsX=X=X=XsX=X=X=XsX=X=X=X=X=XsX=XsX=X=X=XsXsX=X=X=XsX=X", -"=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=XsX=X=XsX=X=X=X=X=X=X=XsX=X=X=XsX=X=X=X=X=X=X=X=XsX=X=XsX=X=X=XsX=X=XsX=X=X=X=XsX=X=XsX=X=X=X=XsX=X=XsX=X=X=X=XsX=X=XsX=X=X=X=X=X=X=XsX=X=XsX=X=XsX=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=XsX=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=XsX=X=XsX=X=X=XsX=X=XsX=X=X=X=X=XsX=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=X=XsX=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=XsXsX=X=XsX=X=X=XsX=X=XsX=X=X=XsX=X=XsXsX=X=X=XsX=XsX=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=XsX=X=XsX=X=XsX=X=XsX=XsX=X=X=XsXsX=X=XsX=X=X=XsX=X=XsX=X=X=X=X=XsX=XsX=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=XsX=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=XsX=X=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX", -"=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=XsX=X=XsXsX=X=X=X=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=XsX=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=XsX=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=XsX=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=XsX=X=XsXsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=XsX=X=X=X=XsX=X=XsXsX=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=XsXsX=X=X=X=X=XsX=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=XsX=X=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=XsX=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsXsX=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=XsXsX=X=X=X=XsX=X=XsX=X=X=X=X=X=XsX=XsX=X=X=X=XsX=X=XsXsX=X=X=X=XsXsX=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=XsX=X=XsX=X=X=X=XsX=XsX=X=X=XsX=X=X=X=X=X=X=X", -"=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=XsX=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X", -"=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X", -"=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X*X=X=X=X=X*X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X*X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X*X=X=X=X=X*X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X*X=X=X=X*X=X*X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X*X*X=X*X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X=X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X*X=X=X=X=X=X=X*X*X=X=X*X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X*X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X*X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X*X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X", -"=X=X*X=X=X*X*X=X=X=X=X=X*X=X=X=X=X=X=X*X=X*X=X*X=X=X=X*X=X*X*X=X*X=X*X=X=X=X=X=X*X=X=X*X*X=X*X=X=X=X=X*X=X*X*X=X*X=X*X=X=X=X=X=X*X=X=X*X=X*X=X*X=X*X*X=X=X*X*X=X*X=X*X=X=X=X=X*X*X=X=X*X=X*X=X*X*X=X=X=X*X=X=X=X=X=X=X*X=X=X=X=X=X=X*X=X=X*X*X=X*X=X=X=X*X=X=X=X=X=X*X=X=X*X*X=X=X=X=X=X*X=X=X=X=X=X=X*X=X*X=X*X=X=X=X*X=X*X*X=X*X=X*X=X=X=X=X=X*X=X*X=X*X=X*X=X=X=X=X*X=X*X=X=X*X=X*X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X*X=X*X=X*X=X=X*X=X*X=X*X=X*X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X*X=X=X*X=X*X*X=X=X=X=X*X*X=X=X=X=X=X*X=X=X=X*X=X*X=X=X=X=X*X*X=X*X=X=X*X=X*X=X*X=X*X=X*X*X=X*X=X*X=X=X=X=X*X=X*X*X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X*X*X=X*X=X*X=X=X=X=X=X=X=X=X=X=X*X*X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X*X=X=X=X=X=X=X=X*X=X=X*X=X*X=X=X*X=X*X=X*X=X*X=X*X*X=X=X=X*X=X=X=X*X=X*X=X*X=X*X=X*X=X*X*X=X*X=X*X=X=X=X=X*X=X*X*X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X*X=X*X=X=X*X=X*X=X*X=X*X*X=X=X*X*X=X*X=X*X=X=X=X=X*X=X=X=X=X=X=X*X=X=X*X*X=X=X=X=X=X*X=X=X=X=X=X=X*X=X=X=X*X=X*X*X=X=X*X*X=X*X=X*X=X=X=X=X=X=X*X*X=X*X=X*X=X=X=X=X=X=X*X=X=X*X=X*X=X=X=X=X=X", -"=X=X*X=X=X=X*X=X=X=X=X*X=X=X=X*X=X=X=X=X*X=X=X=X=X=X*X=X=X=X*X=X=X*X*X=X=X*X*X=X=X=X=X=X=X=X=X*X*X=X=X*X=X=X=X=X=X=X*X=X=X*X*X=X*X=X=X*X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X*X=X=X*X*X=X=X*X*X=X=X=X=X=X*X=X=X=X*X=X*X=X=X=X*X=X=X*X=X*X=X=X=X*X=X=X=X=X*X=X=X=X*X=X=X=X*X=X=X*X=X=X=X=X=X*X=X=X=X*X=X=X=X=X*X=X=X=X=X=X*X=X=X*X=X=X=X*X*X=X=X*X*X=X=X=X=X=X=X=X=X*X*X=X=X*X=X=X=X=X=X=X*X=X=X*X*X=X=X*X*X=X=X*X=X=X=X=X=X=X*X=X=X=X*X=X=X=X=X=X=X=X=X*X*X=X=X*X=X=X*X=X=X*X=X=X=X*X=X*X=X=X=X=X=X=X=X=X*X=X=X=X*X=X*X=X=X*X=X=X=X*X=X=X=X*X*X=X*X=X=X=X=X=X*X=X=X=X=X=X=X*X=X=X=X=X=X=X=X*X*X=X=X*X=X=X=X=X=X=X=X*X*X=X=X*X=X*X*X=X=X*X*X=X=X*X*X=X=X=X=X=X=X=X=X*X=X*X*X=X=X*X*X=X=X=X=X=X=X=X=X*X*X=X=X*X=X*X*X=X=X*X*X=X=X*X*X=X*X=X=X*X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X*X=X*X*X=X*X=X=X=X*X=X=X*X=X=X=X=X=X=X=X*X*X=X*X=X=X=X=X=X=X=X=X*X*X=X*X=X=X*X*X=X=X=X=X=X*X=X=X*X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X*X=X*X=X=X*X*X=X=X=X*X=X=X*X=X=X=X=X=X*X=X=X*X=X=X=X*X=X*X=X=X=X=X=X*X=X=X*X=X=X=X*X*X=X=X*X*X=X=X=X=X*X=X*X=X*X*X=X=X*X=X=X*X=X=X*X*X=X=X*X*X=X", -"=X=X=X*X*X=X=X*X=X*X*X=X=X*X*X=X=X*X*X=X=X*X*X=X*X=X=X*X*X=X=X*X*X=X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X=X=X*X=X=X*X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X=X*X=X=X*X*X=X*X=X=X*X*X=X=X*X=X*X*X=X=X*X*X=X*X=X=X*X*X=X=X*X*X=X=X*X*X=X=X*X*X=X=X*X*X=X=X*X=X*X*X=X*X=X*X=X=X*X*X=X=X*X*X=X*X=X=X*X*X=X=X*X*X=X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X*X=X*X*X=X*X=X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X*X=X=X*X*X=X=X*X*X=X*X=X*X=X*X*X*X=X*X=X=X*X*X=X=X*X=X*X*X=X=X*X*X=X=X*X=X*X=X=X*X=X*X=X*X*X=X*X=X*X*X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X=X=X*X=X=X*X*X=X*X*X=X*X=X*X*X=X=X=X*X=X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X=X=X*X=X=X*X=X*X=X=X*X=X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X*X=X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X*X=X*X=X=X*X=X=X*X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X=X=X=X*X*X=X=X*X=X*X*X=X*X=X=X*X=X*X=X*X=X*X*X=X*X=X=X*X*X=X=X*X*X=X=X=X*X=X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X=X*X=X=X*X=X=X=X*X", -"=X*X*X=X*X=X=X*X=X*X*X=X*X=X=X*X=X*X*X=X*X=X=X*X*X*X*X=X=X*X*X=X=X*X=X*X*X*X=X*X=X*X=X=X*X*X=X*X=X=X*X*X*X=X*X*X=X*X=X*X=X=X*X*X*X*X=X=X*X=X*X=X*X=X*X=X=X*X=X=X*X*X=X*X=X=X*X*X=X*X*X*X=X*X=X*X*X=X=X*X*X*X*X=X*X=X=X*X*X*X*X=X*X=X=X*X=X*X*X=X*X=X=X*X=X*X*X=X=X*X*X*X*X=X=X*X=X*X*X=X*X=X=X*X*X=X=X*X=X*X*X=X*X=X=X*X*X=X*X=X=X*X=X*X*X*X=X*X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X=X*X=X=X*X*X=X*X*X=X=X*X*X=X*X=X*X=X=X*X*X=X=X*X*X=X=X*X*X*X*X=X*X=X=X*X*X*X*X=X*X=X*X=X=X*X=X=X*X*X=X*X=X=X*X*X=X*X*X*X=X*X=X*X*X*X=X*X*X=X*X=X*X*X=X*X*X=X*X=X*X=X*X=X*X=X*X=X*X=X*X=X*X=X*X=X*X=X*X=X=X*X=X=X=X=X*X=X=X*X=X=X*X=X=X*X=X=X*X=X*X=X*X*X=X*X*X=X*X*X=X*X=X*X=X=X*X*X=X*X=X*X*X*X=X*X=X*X=X=X*X*X=X*X=X=X*X*X=X*X=X=X*X*X*X=X*X*X*X=X=X*X=X=X*X=X=X*X*X*X=X*X=X*X*X*X=X*X*X=X*X=X*X=X*X=X*X=X*X=X=X*X=X=X*X=X=X*X=X=X*X=X=X*X*X*X=X*X=X*X*X*X=X*X=X*X=X=X*X*X=X*X*X=X*X=X=X*X*X=X*X=X*X=X=X*X*X=X*X=X=X*X*X=X*X=X*X=X=X*X*X=X*X=X=X*X*X=X*X*X=X*X*X*X=X=X*X=X*X=X*X=X*X=X=X*X=X=X*X*X=X*X=X=X*X*X", -"*X=X*X*X*X*X*X=X*X=X*X*X*X*X*X=X*X*X=X*X*X*X*X*X=X=X*X*X*X*X=X*X=X*X*X=X=X*X=X*X*X*X*X*X*X=X*X*X*X*X*X=X*X=X*X=X=X*X*X*X*X*X*X=X=X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X=X*X=X=X*X=X*X*X=X*X*X*X=X=X=X*X*X*X*X*X=X=X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X=X=X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X=X=X*X*X*X=X*X*X=X=X*X=X*X=X*X*X=X*X*X=X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X=X*X*X*X=X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X=X=X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X=X=X*X*X*X*X*X=X=X=X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X=X*X=X=X*X=X*X*X*X=X*X=X*X=X*X*X*X=X*X=X*X=X*X*X*X*X*X=X*X*X*X*X*X=X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X=X*X*X*X=X*X=X*X*X*X*X*X*X*X=X*X*X*X*X=X*X*X=X*X*X*X*X*X=X*X*X*X*X*X=X*X*X*X*X*X=X=X*X*X=X*X*X*X*X*X*X*X*X*X=X=X*X=X*X*X=X=X*X=X*X=X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X=X*X=X*X*X=X=X*X=X*X*X*X*X*X*X=X*X*X=X*X*X*X*X*X=X*X=X*X*X*X*X*X=X*X*X*X*X=X=X*X*X*X*X*X*X=X=X*X*X*X=X*X*X=X=X*X=X*X=X*X*X*X*X*X=X*X*X*X*X*X*X=X*X*X*X=X*X*X*X*X*X=X", -"*X*X=X*X*X=X*X*X*X*X=X*X*X=X*X*X*X=X=X*X=X*X*X=X*X*X=X*X*X=X*X*X*X=X*X*X*X*X*X*X*X=X=X*X*X=X*X=X=X*X*X*X*X*X*X*X=X=X*X=X=X*X*X*X=X*X*X*X*X*X*X*X*X=X=X*X*X=X=X*X*X=X*X=X=X*X*X=X*X*X*X*X*X=X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X=X*X*X*X*X=X*X*X=X*X*X*X*X*X=X*X*X=X*X*X=X*X=X=X*X=X*X*X=X=X*X*X=X*X*X=X*X=X*X*X*X*X*X=X*X*X=X*X*X*X*X*X*X=X*X*X*X=X*X=X*X*X=X=X*X*X=X*X*X*X=X*X=X=X*X*X=X*X*X*X*X=X*X=X*X*X=X=X*X=X*X*X*X*X*X*X=X=X*X*X=X*X=X=X*X*X=X*X=X*X=X*X*X*X*X*X=X*X=X*X*X=X*X*X=X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X=X*X=X=X*X*X=X*X=X=X*X*X*X*X*X*X*X*X=X*X=X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X=X*X*X*X*X=X=X*X=X*X*X*X=X*X*X*X*X=X=X*X*X=X=X*X=X*X*X=X*X=X=X*X*X*X*X=X*X=X*X=X*X*X*X*X=X*X=X*X*X=X=X*X=X*X*X*X*X=X=X*X*X=X*X*X*X=X*X=X*X*X*X*X*X=X=X*X*X=X*X=X*X*X*X*X=X*X*X*X*X*X*X=X=X*X*X=X*X*X*X*X*X=X*X*X*X*X*X*X=X*X*X*X=X*X*X*X*X=X=X*X*X=X=X*X*X=X*X=X=X*X*X=X*X*X*X*X*X=X*X*X*X*X*X*X*X=X=X*X*X=X*X=X*X*X*X=X*X=X*X*X*X*X*X=X*X=X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X=X*X*X=X*X*X*X*X*X=X*X*X*X=X*X*X*X*X=X=X*X=X*X*X*X*X=X*X=X*X*X*X=X", -"*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X=X=X*X*X=X&X*X*X*X*X*X*X=X*X*X*X*X=X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X=X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X=X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X=X*X*X*X*X=X*X*X*X*X=X*X*X*X*X*X*X*X=X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X", -"*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X", -"*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X=X&X&X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X%X*X*X*X*X*X*X*X%X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X%X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X&X%X*X*X&X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X%X*X*X*X*X%X*X*X*X&X*X*X%X&X*X*X*X*X%X*X*X*X*X*X&X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X&X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X", -"*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X&X=X&X*X=X*X*X&X*X*X*X*X&X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X=X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X&X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X", -"%X*X*X*X%X*X*X*X%X*X*X*X%X*X*X*X*X*X%X*X%X*X*X*X%X*X*X*X%X*X*X*X*X%X*X*X%X*X*X%X%X*X*X%X*X*X*X*X*X%X}.V.k.g.d.g.k.V.!.@X%X*X*X&X*X%X*X*X*X%X%X*X*X*X%X*X%X*X*X*X*X%X*X%X*X*X*X%X*X%X*X*X%X*X*X&X*X%X*X*X*X*X%X*X*X%X*X*X*X*X%X*X%X*X*X*X*X%X*X*X%X*X*X*X*X%X*X*X*X*X%X*X*X*X*X*X*X*X%X*X*X*X*X=X*X&X&X!.k.g.d.g.k.V.`.&X*X&X*X=X*X%X*X*X%X*X*X%X%X*X*X*X%X*X*X*X*X*X*X%X*X%X*X*X*X%X*X%X*X*X%X*X%X*X*X*X%X*X*X*X*X*X*X%X*X%X*X*X*X%X%X*X*X*X%X*X*X*X*X%X*X*X*X*X*X%X*X*X*X*X%X*X*X%X*X*X*X*X&X*X*X%X*X*X*X*X%X*X*X%X*X*X*X*X%X*X&X*X*X&X%X*X*X*X*X%X%X*X%X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X%X*X%X*X*X*X*X%X*X*X*X%X*X*X%X*X*X*X*X*X%X*X%X*X*X*X&X*X*X*X*X*X*X%X*X*X$X*X*X*X%X*X%X*X*X*X%X*X%X*X*X*X*X%X*X%X*X*X*X*X+XV.k.g.d.d.g.V.!.}.*X&X*X*X%X*X*X*X%X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X*X*X%X*X*X*X*X*X*X*X*X*X*X%X*X%X*X*X*X%X*X*X*X*X*X*X%X*X*X*X*X*X*X%X*X%X*X*X%X*X*X*X*X%X*X*X*X*X*X%X*X*X*X*X*X%X*X*X*X*X%X*X*X%X*X*X*X*X*X&X&X*X%X*X*X*X*X%X*X*X%X*X*X*X*X*X*X%X&X*X*X%X*X*X%X*X*X%X*X*X*X*X*X*X*X%X*X%X*X*X*X*X%X*X%X*X*X*X*X", -"*X*X%X*X*X%X*X*X*X%X*X*X%X*X*X%X%X*X*X%X*X*X%X*X*X%X*X*X%X*X*X%X*X%X*X*X*X%X*X*X%X*X*X%X*X!.-.b 2 X $ w Z y.`.*X*X*X*X*X&X*X*X*X%X*X*X%X*X*X*X%X*X*X*X%X*X*X*X%X&X*X&X*X*X%X*X%X&X*X*X&X*X%X&X*X*X%X&X*X&X*X*X%X*X*X*X%X*X*X&X*X*X%X*X*X%X*X%X*X*X%X*X*X%X*X%X*X*X&X*X%X!.-.M < . X < h #.V.&X=X&X%X*X%X*X*X%X*X*X%X*X%X*X*X%X*X*X*X*X*X*X&X*X%X*X*X*X%X*X*X*X*X&X*X*X*X&X*X*X*X*X&X%X*X*X%X*X&X*X*X*X*X%X*X*X*X%X*X*X*X%X*X%X*X*X*X%X*X*X%X*X*X%X*X*X%X&X*X*X%X&X*X*X&X*X%X&X*X*X%X&X*X&X*X%X*X*X&X%X*X*X&X*X%X&X*X*X%X*X*X=X*X&X*X*X*X*X*X*X*X*X&X%X*X*X&X*X%X*X*X*X*X*X*X*X*X&X*X%X*X*X%X*X%X*X*X%X*X*X&X*X*X*X&X%X*X*X&X*X%X*X*X*X*X&X*X%X*X*X%X*X*X%X*X%X*X*X%X*X*X*X*X*X*X*X*X*X&XV.#.b * $ e Z y.`.*X*X&X*X%X%X*X%X*X*X%X*X*X%X*X%X*X*X%X*X*X%X&X*X*X*X%X&X*X*X%X%X*X*X&X%X*X*X&X*X*X&X*X*X%X&X*X&X*X*X&X*X%X&X*X&X&X*X&X%X*X*X*X%X&X*X*X*X*X%X*X*X*X%X*X*X*X%X*X*X%X=X*X&X*X*X*X=X*X*X%X%X&X*X*X*X%X*X*X%X*X*X%X*X%X*X*X%X*X*X%X*X*X%X*X%X*X*X%X*X*X%X*X%X*X*X%X*X%X*X*X%X*X*X*X*X%X*X%X*X*X*X%X", -"*X%X*X*X%X*X*X%X*X%X%X*X*X%X*X%X*X%X*X%X%X*X*X%X*X%X%X*X*X%X*X%X%X*X*X%X*X%X%X*X*X%X`.#.; . 5 #.}.*X%X*X%X%X%X*X*X%X*X%X%X%X*X*X%X*X%XZ m m m m m m m M m m m m m M m m m m m M m m m m m m m m m m m m m T &X%X*X*X%X*X%X*X%X*X%X%X*X%X*X*X&X%X}.Y 5 @ H !.*X*X&X%X*X*X%X%X*X%X*X*X%X*X*X%X%X%X%X*XB h h h h h h h h h h h h h h h h h h h m *X%X*X*X%X}.h h h h h h h h h h h h h h h h h h h h #.*X%X*X*X%X%X*XV.m m m m m M m m m m m M m m m m m m m m m m m m m m m m m m m m m m x.*X%X*X%X%X*XV.h h h h h h h h h h h h h h h h h ).*X*X%X%X*X*X%X%X*X%X!.h h h h h h h h h h h h h h h h h `.%X*X*X%X*X%X%X*X*X%X%X*X*X%X%X*X%X%X*XV.J = 9 P `.%X*X*X*X*X*X%X*X%X%X*X*X*X%X%X*X%X*X*Xd.m m m m m m m m m m m m m m m m m M m m M m m m m m M m m m m m m m }.%X*X*X%X%X*Xh.m m m m m m M m m m m m m m Z Z Z Z Z Z Z P P #.-.y.u.g.x.`.}.*X*X*X*X%X%X*X*X%X*X%X%X*X%X*X%X*X*X%X*X*X%X*X%X*X%X*X*X*X%X*X%X*X%X%X*X*X%X%X%X*X%X*X*X%X%X*X", -"%X*X%X%X%X*X%X*X%X*X%X*X*X*X%X*X%X*X%X*X%X*X*X%X%X*X%X*X%X*X%X*X%X*X%X*X%X*X*X*X`.M . Z `.&X&X*X%X*X%X*X*X*X*X%X*X%X*X*X*X= e %X%X*X%X*X%X*X*X*X%X*X%X*X*X%X&X}.J X w k.&X%X*X*X%X*X%X%X*X*X*X%X*X%X*X*X%X*X< & %X*X*X%X*X`. M *X*X%X*X%X*X%Xg. s.*X%X%X%X*X%XV. P *X*X%X*X%X%X*X%X*X*Xx. `.*X*X*X*X*X*X*X%X*X*X%X*X%X*X%X%X*Xk.w b V.*X*X%X*X*X%X*X%X*X%X*X%X*X*X*X%X*XT `.&X%X*X%X*X*X-. @ w Z u.`.*X%X%X*X*X&X*X*X*X*X%X*X*X%X*X%X%X*X%X*X*X%X*X%X%X*X*X%X*X*X%X*X%X*X*X*X*X*X*X*X*X%X", -"%X*X%X*X%X*X%X%X*X%X*X%X%X%X*X%X*X%X*X%X*X%X*X%X*X%X*X%X*X%X*X%X%X%X*X%X*X%X+XZ Z }.*X%X%X*X%X%X%X%X%X*X%X%X%X&X& h *X%X*X*X%X*X%X%X%X*X%X*X%X*X%Xu.# w V.$X%X*X%X*X*X%X%X%X%X%X*X%X*X%X*X< & *X%X%X*X%X`. M &X*X%X%X*X%X*Xg.. d.%X*X%X*X%X*Xk. 5 %X%X*X%X*X*X%X*X%X%XV. ).%X%X%X%X%X%X*X%X%X%X*X*X*X%X*X}.m X H +X*X%X*X%X%X*X%X*X%X*X%X%X*X%X%XT ).*X%X%X*X%X*X-. 9 k.*X%X%X&X%X%X%X%X*X%X*X%X%X*X%X*X*X%X*X%X%X*X%X*X%X*X%X%X*X%X*X%X%X%X%X%X%X%X%X*X", -"*X%X*X%X*X%X*X%X%X*X%X*X%X%X%X%X%X*X%X*X%X*X%X%X%X*X%X*X*X&X%X%X*X%X*X%X%X!.7 & k.%X%X%X%X*X%X*X*X%X%X*X%X%X$ e &X%X%X*X%X%X&X%X*X&X%X%X*X@Xm J @X*X%X%X%X*X*X%X*X%X*X%X%X*X%X< & %X&X%X%X%X`. M *X*X%X%X%X%X%Xg. u.=X%X%X*X%X*Xk. V.%X*X%X%X&X%X&X*X%Xx. ).*X%X*X%X%X%X*X%X%X*X%X%X*X&Xg.# 5 V.%X%X&X&X%X*X%X%X*X%X%X*X%X*XY ).%X%X*X%X*X%X-. b }.%X%X%X&X%X%X%X%X*X%X%X*X%X%X%X%X*X%X%X*X%X%X%X%X%X*X*X%X%X*X%X%X%X%X%X*X%X%X", -"%X%X%X%X%X%X%X%X%X%X%X%X%X*X%X*X%X%X%X%X%X%X%X%X&X%X%X%X%X%X%X%X%X%X%X%X!.+ X u.&X%X%X*X%X%X%X%X%X*X%X%X& h %X%X&X%X%X&X%X%X%X%X%X%X}.w e }.%X%X%X%X%X&X%X%X%X%X%X*X%X< # &X%X%X*X%X`. M %X%X%X%X*X%X*Xg. d.*X%X%X%X%X%Xk. #.%X%X%X*X%X%X%X%X%XV. `.%X%X%X%X%X*X%X%X%X*X%X%X%X#. u.%X%X%X&X%X%X%X%X%X*X%X%X%XY ).*X%X&X%X%X*X-. & V.%X*X%X%X%X%X%X%X%X%X%X*X%X*X%X%X%X%X%X%X*X%X*X%X%X%X%X%X%X%X*X%X*X%X%X*X%X", -"%X%X%X%X%X%X%X%X*X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X).# s.%X%X%X%X%X%X%X%X%X%X$X& e %X%X%X%X%X%X%X%X%X%X%X+Xe 5 }.%X%X%X%X%X%X%X%X%X%X%X%X< & $X%X%X%X%X_.. M %X%X%X%X*X%X%Xg. s.%X%X%X%X%X%Xk. 7 %X%X%X%X%X&X%X%X%Xx. ).%X%X%X%X%X%X%X$X%X%X%X%XP :.&X%X%X%X%X%X%X%X%X%X%X%XT ).%X%X%X%X$X$X-.. o V.%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X*X%X$X%X", -"%X%X*X%X%X%X%X%X%X%X%X$X*X%X%X%X%X%X%X%X%X%X*X%X%X%X%X%X%X%X%X%X%X%X&X7 . `.%X%X%X%X%X%X%X%X%X*X$ h %X%X%X%X%X%X%X%X%X%X%XB w +X%X%X%X%X%X%X%X%X%X%X%X< $ %X%X%X%X%X`. . M %X%X%X%X%X%X%Xg. s.%X%X%X%X%X$Xx. `.%X%X%X%X%X%X%X%Xx. ).%X%X%X*X%X%X%X%X%X%X%X-. u.%X%X%X%X%X%X%X%X%X%X*XY ).%X%X%X%X%X%X-. * `.%X%X%X%X*X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X*X%X%X%X$X*X%X%X$X%X%X%X", -"%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X$X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X#. b %X%X%X%X%X%X$X$X%X%X$ h %X%X%X%X%X%X%X%X%X%Xs. Z %X%X%X%X%X%X%X%X%X%X%X< $ %X%X%X%X%X`. M %X%X%X%X%X%X$Xg. s.%X%X%X%X%X%Xz. #.%X%X%X%X%X%X%X%Xx. ).%X%X%X%X%X%X%X%X$X%Xx. @ ).%X%X%X%X%X%X%X%X%X%XY ).$X%X%X%X%X%X-. h %X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X$X%X%X%X%X%X%X%X%X%X%X%X%X%X", -"$X%X%X$X$X%X%X$X$X%X$X%X%X%X%X%X%X%X$X%X%X$X%X%X$X%X%X#X%X%X$X%X%X+X@ !.%X$X%X$X%X%X%X%X%X& e %X%X$X%X%X$X%X%X%X`.@ k.$X%X%X%X%X%X$X%X%X%X< & %X%X$X%X$X_. M %X%X%X%X%X$X%Xg. s.%X%X$X%X%X$Xk. w %X%X%X%X$X$X%X%Xx. ).$X%X%X$X%X%X%X%X$X+X< 9 %X%X%X%X%X$X%X%X%X%XY ).%X%X%X$X%X%X-. u.%X%X$X%X$X%X%X$X%X$X$X%X$X%X%X$X%X%X%X%X%X%X%X%X$X%X%X$X%X%X$X%X%X$X", -"$X%X$X%X$X%X$X%X%X$X%X%X$X%X$X%X%X$X%X$X@X%X%X$X%X$X%X%X%X@X#X%X%X:. T $X$X%X$X%X$X%X%X%X$ e %X%X$X%X$X%X%X$X%XB 7 @X%X$X$X%X$X%X$X%X%X< $ %X$X%X$X$X`. M $X%X$X%X$X$X$Xg. s.%X%X$X$X$X%Xk. `.$X$X$X%X$X%X%Xx. ).$X%X$X%X%X%X$X$X$X#. g.$X$X$X$X$X%X$X%X%XY ).%X%X$X%X$X%X#. 5 $X$X%X$X$X%X$X%X$X$X%X$X$X%X$X%X%X%X$X%X$X$X%X$X%X$X%X$X%X$X$X%X$X%X", -"%X$X%X$X%X$X%X%X$X%X%X%X%X$X%X$X$X%X$X%X%X%X$X%X#X%X%X#X$X%X%X%X$Xh 9 $X%X$X$X%X%X$X%X$X& h $X$X$X$X%X$X$X%X). s.$X$X%X$X%X$X%X$X%X< $ $X%X$X%X%X_. M $X%X%X$X%X%X$Xg. s.%X%X$X%X%X$Xz. -.$X%X%X$X%X$X$XB. ).%X$X%X%X%X$X%X%X}.X 9 $X%X$X%X%X$X%X$X%XY ).$X$X%X$X%X$X-. h.%X$X%X%X$X%X$X%X%X$X%X%X$X%X$X%X%X%X$X%X%X$X%X$X%X$X%X$X%X%X$X%X$X", -"$X$X%X$X$X%X$X$X$X%X$X$X$X$X%X$X$X$X$X$X$X$X$X$X%X%X$X$X%X#X$X$X+XX X +X$X$X$X%X$X$X%X$X# w %X$X$X$X$X$X%X$XZ 9 %X$X$X$X$X$X$X%X%X< $ %X%X%X$X$X`. M $X$X$X$X$X$X$Xg. u.$X$X$X$X%X$Xk. h $X%X$X$X%X$X%XB. ).$X%X$X$X$X$X$X$X#. V.$X%X$X$X%X%X$X$XY ).%X$X$X%X$X%X-. Z %X$X%X$X%X$X$X%X$X$X%X$X%X$X$X$X$X$X$X$X%X$X$X%X$X%X$X%X$X$X%X$X$X", -"$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X%X$X$X$X$X$X$X$X$X$X%X$X$XV. b f.V.s.* V.$X$X$X$X%X$X$X$X$ h $X$X$X$X$X$X$X@X@ $ :.V.f.e V.#X%X$X$X$X$X$X$X< $ %X$X$X$X$X_. M $X$X$X$X$X$X$Xg. s.$X$X$X$X$X$Xz. _.$X$X$X$X$X$Xk. _.$X$X$X$X$X$X$X$X9 m f.V.g.M #.$X$X$X$X$X$X$X$XY (.$X$X$X$X$X$X-. & $X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X", -"$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X-. Z $X$X$X%XV. s.$X$X$X$X$X$X$X$X& e $X$X$X$X$X$X$Xl. z.$X$X$X+X% #.$X$X$X$X$X$X$X$X< $ $X$X$X$X$X_. m $X$X$X$X$X$X$Xg. s.$X$X$X$X$X$Xk. :.$X$X$X$X$X$Xx. (.$X$X$X$X$X$X$X). Z $X$X$X$X$XM h $X$X$X$X$X$X$X$XY (.$X$X$X$X$X$X-. ).$X$X$X$X$X$X$X$X$X$X$X$X#X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X", -"$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$XY . {.$X$X$X#X#X7 #.$X$X$X$X$X$X$X%X$ e $X$X#X$X$X$X$XP 7 %X$X$X$X$XZ h $X$X$X$X$X$X$X$X< & $X$X$X#X$X_. M $X$X$X$X#X$X$Xg. s.$X$X$X$X$X$Xz. h %X$X$X$X$X$Xx. ).$X$X$X$X$X$X$Xs. V.$X$X$X$X$Xf. @ $X$X$X$X$X$X$X$XY ).$X$X$X$X$X$X-. u.{.V.u.e h.$X$X$X$X$X$X$X$X#X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X", -"$X$X$X$X#X$X#X$X#X#X#X#X#X@X$X$X$X#X$X$X#X$X$X$X#X$X$X#X$X$X$X$XM w #X$X#X#X$X$XM L $X$X$X$X$X$X$X$X# h $X$X$X$X$X$X$Xl B $X#X$X$X$X-. # $X#X$X#X$X$X$X$X< $ $X$X#X$X$X_. M $X$X$X$X#X$X$Xf. s.$X$X$X$X$X$Xz. . {.$X$X#X$X$Xz. (.$X$X#X$X$X$X#XL o $X$X#X$X#X$X_. _.#X$X$X$X$X$X@XO. (.$X$X$X$X#X#X-. s.$X#X#X#XP -.@X$X#X#X@X$X#X$X$X#X$X#X$X$X$X$X$X#X$X$X$X$X$X#X#X$X$X$X#X$X#X$X", -"#X#X#X#X$X#X$X$X#X#X$X#X#X#X$X$X#X$X#X$X#X#X#X$X#X$X#X$X#X#X#X#Xe m $X#X$X#X#X$XZ M #X#X$X#X#X#X#X#X# # d.d.d.d.d.s.d.d.d.d.d.d.d.z.#X#X#X#X#X#X$X< L #X$X$X#X$Xf. }.$X$X#X$X#X#X$X< # $X$X#X#X$X_. M #X$X$X#X$X#X$Xf. M d.d.d.d.d.d.d.d.d.d.d.d.d._.$X$X#X#X$X#Xz. u.#X$X$X#X$Xz. (.$X$X$X#X#X$X#XM 5 #X$X#X$X$X#X#X h.#X#X#X$X#X#X@XY P f.d.d.d.d.d.d.d.d.d.d.d.d.XX#X$X#X#X#X$X=. 4.#X#X#X$X#X* Z $X#X#X#X$X$X#X#X$X#X#X$X#X#X#X$X#X$X#X#X#X#X#X#X#X#X#X$X#X$X$X#X", -"#X#X#X$X#X#X#X#X#X@X$X$X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X7 H #X#X#X#X#X#XL l #X#X#X#X#X#X#X$X& * $X#X#X#X#X#X#X#X#X#X#X#X#X#X#X$X#X#X#X#X$X. #.$X#X#X#X#Xh. B.#X#X#X#X#X#X#X< & #X$X#X#X$X_. M #X#X#X#X#X#X$Xf. #.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#Xz. l #X#X#X#X#Xz. (.#X#X#X#X#X#X#Xh w #X#X#X#X$X#X#XX -.#X#X#X#X$X#X$X#. h.#X#X#X#X#X#X#X#X#X#X#X$X#X$X#X$X#X#X#X#X=. s.#X#X#X$X#XN h #X#X#X$X#X#X#X#X$X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X$X#X#X#X#X#X#X", -"#X#X#X#X#X#X#X$X#X#X#X#X#X#X#X#X$X#X#X#X$X#X#X#X#X$X$X#X#X#X#X#X< P #X#X#X#X#X#XY h $X#X#X#X#X@X#X$X& * $X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_. #.$X#X#X#X#Xz. f.#X#X#X#X$X#X$X< & #X#X#X#X#X_. M #X#X#X$X#X#X$Xf. #.#X#X#X#X#X#X#X#X#X#X#X#X#X$X#X#X#X#X#X#Xh. X {.#X#X#X$Xz. _.#X#X#X#X#X$X#X7 h #X#X#X#X#X#X#X$ P #X$X#X#X#X#X$XL f.#X#X#X#X#X#X#X#X#X#X#X$X#X#X#X#X#X#X#X#X-. s.#X#X#X$X$X-. w #X#X#X#X#X#X#X#X#X#X#X#X#X$X#X#X$X#X$X#X#X#X#X#X#X#X#X#X$X#X#X#X", -"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X& P #X#XOX#X#X#XY e #X#X#X#X#X#X#X#X# * #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XB. :.#X#X#X#X#XB. :.#X#X#XOX#X#X#X< $ #X#X#X#X#X_. M #X#X#X#X#X#X#Xf. #.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XOX#X#X#Xz. s.#X#X#X#XB. (.#X#X#X#X#X#X#X& l $X$X#X#X#X#X#X* Z #X#X#X#X#X#X#XY h.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X-. s.#X#X#X#X#X>. 9 #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", -"#X#X#XOX#X#X#XOX#X#XOX#X#X#X#XOX#X#XOX#XOX#X#X#X#XOX#X#X#X#X#X#X@ Z #X#X#X#XOX#X#. 9 OX#X#X#X#XOX#X#X$ * #X#X#X#XOXOX#X#X#X#XOX#X#XOX#X#X#X#X#X#Xz. 4.#X#X#X#X#XV. #.#X#X#X#XOX#X#X< & #X#X#XOXOX_. M OXOX#X#X#X#X#Xh. #.#XOXOX#X#X#X#X#X#XOX#X#X#X#X#X#X#X#X#X#Xh. m #X#X#X#XB. (.#X#X#X#X#XOX$XX M #X#X#X#XOX#X#X2 l #XOX#X#X#XOX#XL f.#X#X#X#X#XOX#XOX#X#X#X#XOX#X#X#X#XOX#X#X=. 4.#X#X#XOX#Xs. 2 OX#X#X#X#X#X#X#X#X#XOXOXOX#X#X#X#XOX#X#X#X#XOX#XOX#X#X#X#XOX#X#X", -"#XOX#XOX#XOX#X#XOX#X#X#X#XOX#XOXOX#XOX#X#XOX#XOX#X#XOX#X#XOX#X#X@ h #X#XOX#X#X#X+. 9 OX#XOX#X#X#X#X#X$ * #X#XOX#XOX#X#X#XOX#XOX#XOXOX#XOX#X#XOX#Xh. 4.#X#XOX#X#X^. #.#X#XOX#X#X#X#X< $ #XOX#XOX#X_. x #X#XOX#XOXOX#Xf. Y #XOX#X#XOX#XOX#X#X#X#XOXOX#XOX#XOX#X#X#Xl. X {.OX#X#Xz. (.OX#X#X#X#X#XOX N OX#XOX#X#XOX#X5 w #XOXOX#XOX#X#X#. h.#XOX#XOX#X#X#X#XOX#XOX#X#XOX#XOX#XOX#XOX-. 4.#XOX#X#X#Xs. # #XOX#XOX#X#XOX#XOX#XOX#X#X#X#XOX#X#XOX#XOX#XOX#X#X#X#X#X#X#XOX#X", -"OX#XOX#XOX#XOXOX#XOXOX#XOX#XOX#X#XOX#X#XOX#X#XOXOXOX#XOXOX#XOX#X& @ OXOX#X#XOXOXY 9 #X#XOXOXOX#XOXOX& , #XOX#XOX#XOX#XOX#XOX#X#XOX#XOX#XOXOX#XOXf. 4.#X#XOXOXOX(. Y OXOX#XOXOX#XOX< $ #XOXOXOXOX_. M #XOX#X#XOX#XOXf. #.OX#XOX#XOX#X#XOX#XOXOX#XOX#X#XOX#XOXOXOXh. f.#XOXOXl. (.#XOXOXOXOXOX{. N OX#X#XOXOX#XOX7 7 OX#X#XOX#XOX#XL 8.#X#XOX#XOX#X#XOX#X#XOXOXOX#XOX#XOX#X#XOX=. s.OX#XOXOX#X4. # OX#X#XOXOXOX#XOX#XOX#X#XOXOXOX#X#XOX#XOX#XOX#X#XOXOX#XOXOXOX#XOX", -"#XOX#X#XOXOX#XOXOX#XOXOX#XOX#X#XOXOX#XOX#XOX#X#XOX#XOX#XOX#XOX#X< B.#XOX#X#XOX#. X 9 #XOX#XOX#X#X#XOX& < OX#XOXOX#XOXOX#XOXOX#XOXOX#XOX#X#XOXOX#X6. 4.#XOX#XOX#X^. P OX#XOX#XOX#X#X, # #X#XOX#XOX_. M OXOX#XOX#XOX#Xf. #.#X#X#XOXOX#X#XOXOX#X#X#X#XOXOX#X#XOXOX#Xl. M OX#XOXz. (.#XOXOX#X#XOX{. N OX#X#X#XOX#X#X7 5 #XOX#XOX#X#XOX#. h.OX#XOX#XOX#X#X#XOX#XOX#X#XOX#X#XOX#X#XOX#. 4.OX#XOX#XOXs. * #XOX#XOX#X#X#XOX#XOX#X#X#XOX#XOX#X#XOX#XOX#XOX#XOX#X#XOX#X#XOX#X", -"OX#XOXOXOX#X#XOX#XOXOX#XOX#XOXOXOX#X#XOXOX#XOXOXOXOX#XOX#XOXOXOX9 l #XOXOXOX#Xl.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.>.#XOXOXOXOXOX#XOX$ * #XOX#X#XOXOX#X#XOX#XOXOX#XOX#XOXOXOX#X#X>. s.OXOXOX#XOX^. H #XOX#XOXOXOXOX< & OXOXOX#X#X(. M #XOXOXOXOX#XOXf. +.OXOXOXOX#XOXOX#XOXOXOXOXOXOX#XOXOX#XOXOXj. o OXOX#Xl. ^.OX#XOXOXOXOX{. N OXOXOXOXOXOXOX4 * #XOXOX#XOXOXOXU f.OX#XOXOXOXOXOX#XOXOX#XOXOXOXOXOX#XOXOXOX:. 4.#X#XOXOXOX4. < #XOXOX#XOXOX#XOXOXOXOXOX#XOXOX#XOXOXOXOXOX#X#XOXOXOXOX#XOXOXOXOX", -"OXOXOX#XOXOXOXOXOXOXOXOXOXOXOX#X#XXXOXOXOXOXOXOXOX#XOXOXOXOXOXOXl #.OX#XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX#XOXOXOXOXOXOXOXOXOX# * OXOXOXOX#X#XOXOXOXOXOXOXOXOXOXOX#XOXOX#X:. 4.#XOXOX#XOX^. Z OXOXOXOXOXOX#X< $ OX#XOXOXOX/. M OXOXOXOX#XOXOXf. #.OXOXOXOXOXOXOXOXOX#XOXOXOXOX#XOXOXOXOXOXz. f.OXOXl. (.OXOX#XOXOXOX[. N OX#XOXOXOX#XOX7 & OXOXOXOXOXOXOXY h.OXOXOXOX#XOXOXOXOXOXOXOXOXOX#XOXOXOXOXOX#.X 4.OXOXOXOX#X>. 4 OXOXOXOXOXOXOXOXOX#XOXOXOXOXOXOXOXOXOX#XOXOXOXOXOXOX#XXXOXOXOX#X", -"OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXXXOXOXOXOXOXOXOXOXOX#XXXZ L OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX& * OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX#. 4.OXOXOXOXOX^. N OXOXOXOXOXOXOX< $ OXOXOXOXOX_. x OXOXOXOXOXOXOXf. #.OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXXXj. Z OXOXl. (.OXOXOXOXOXOX_. N OXOXOXOXOXOXOX7 $ OXOXOXOXOXOXOXU f.OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX#.X 4.OXOXOXOXOX-. w OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX", -"OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX:. l {.XXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX$ * OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOX#. 4.OXOXOXOXOX^. N OXOXOXOXOXOXOX< # OXOXOXOXOX_. M OXOXOXOXOXOXOX8. #.OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXj. # XXOXl. ^.OXOXOXOXOXOX(. N OXOXOXOXOXOXOX7 @ OXOXOXOXOXOXOXY f.OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX:. 4.OXOXOXOXOXL M OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXXX", -"OXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXB. . # =.XXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX$ * OXOXoXOXOXOXXXOXOXOXOXOXOXOXOXOXOXOXOXOX:. 4.OXOXOXOXOX^. N OXOXOXOXOXOXOX< & OXOXOXOXOX/. M OXOXOXOXOXOXOXf. U OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXj. j.XXl. (.OXOXOXOXoXOX^. . N OXOXOXOXXXOXXX7 o OXOXOXOXOXOXOXL r.XXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX#. 4.OXOXOXOXXXx L OXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOX", -"OXOXOXoXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXXXX h /.oXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXoXOXOXOXOXOXOXOXOX& , OXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOX+. 4.OXXXOXOXOX^. N OXOXOXOXOXOXOX, % OXoXOXOXOX_. M oXOXOXoXoXOXOX8. +.OXOXoXOXoXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXj. Z OXB. /.OXOXOXXXOXOX^. N OXoXOXOXOXOXXX7 o OXOXOXoXOXOXOXO. r.OXOXOXOXOXOXOXOXoXOXOXOXOXOXOXoXoXOXOXOX+. 6.OXOXoXOXXX$ =.oXOXOXOXOXOXXXOXOXOXOXOXOXoXOXOXOXOXoXoXOXOXOXOXOXOXOXOXOXOXOXOX", -"OXoXOXOXoXoXOXOXoXOXOXOXOXoXOXoXOXoXOXoXoXOXoXOXoXOXOXoXOXoXOXXXoXM H {.OXOXOXoXOXoXoXOXoXOXoXOXOXoXOXOXOXoXOXoXOXoXOXoX$ * OXOXoXOXOXOXoXOXoXoXOXoXOXOXOXOXoXOXOXOX#. 4.OXoXOXOXXX^. N oXOXoXOXoXOXOX< % OXOXoXOXOX/. M oXOXOXOXOXOXoXf. #.oXOXOXOXOXOXOXoXOXOXoXOXoXoXOXOXOXoXOXOXj. * XXl. ^.oXOXOXXXOXXX^. N OXOXoXoXOXXXOX4 o OXoXOXOXoXOXXXY f.OXoXOXOXoXOXoXOXOXoXOXXXOXoXOXOXOXOXoXOX=. 4.OXOXOXOXL B.oXOXOXoXOXoXOXOXOXoXOXoXOXOXoXOXOXOXOXOXOXoXoXOXOXoXOXOXoXoXOXOX", -"OXoXOXOXOXOXOXOXOXOXoXOXoXOXOXOXOXOXoXOXOXOXoXOXOXoXOXOXOXOXOXOXOX6. 3 j.OXOXOXOXoXOXoXOXOXOXOXoXOXOXoXOXOXOXOXoXOXOXoX% o L L L L L I L L L L L U #.OXOXOXOXOXoXOX;. 4.OXoXOXOXOX^. N OXOXoXOXOXOXOX, & OXOXoXOXoX_. M oXOXOXOXoXOXOXf. w L L L L L I L L L L L L l.OXOXoXOXOXoXOXj. B.j. ^.oXOXOXoXOXOX^. N OXoXOXOXoXOXOX7 @ OXoXOXOXoXOXOXU x L L L L L L L L L L L L /.oXOXoXOXOXOXoX=. L 6.>.U 3 @ XXOXOXoXOXOXOXoXOXOXOXoXOXOXOXoXOXOXOXoXOXOXoXOXOXOXoXOXOXoXOXOXoX", -"oXOXOXoXoXOXoXoXoXOXOXoXOXOXoXOXoXoXOXOXoXoXOXOXoXOXoXOXoXoXOXoXoXXX< l [.oXOXOXOXOXoXoXOXoXOXOXoXOXOXoXoXOXOXoXoXOX$ 2 OXoXoXOXoXOXoX=. 4.oXOXoXoXOX^. N oXOXOXoXOXoXOX< # oXOXOXoXOX/. M oXoXoXOXOXoXOX8. #.oXOXoXoXOXOXoXj. H B. /.OXOXoXOXOXoX^. X N oXOXOXoXOXOXoX3 o oXOXOXoXOXOXoXU j.OXOXOXOXoXoXOX=. x oXoXOXOXoXoXOXOXoXoXOXOXoXoXOXOXoXoXoXOXOXOXOXoXoXoXOXoXOXOXoXoXOX", -"oXOXoXoXOXoXoXoXoXOXoXOXoXoXoXOXoXOXOXoXOXoXOXoXOXOXoXoXoXOXoXoXOXoX;. # 6.OXoXoXoXoXOXoXOXoXoXoXOXoXoXOXoXoXOXOXOX% 2 oXOXoXoXoXOXOX*. 4.oXOXoXOXoX^. N OXoXoXoXoXOXoX< $ OXoXoXOXoX/. x OXoXOXOXoXOXoX8. +.oXOXOXoXoXoXOXj. & B. ^.OXoXOXoXoXOX^. N oXOXoXoXOXoXOX7 @ oXOXoXoXOXoXXX#. j.OXoXoXoXoXOXOX=. h.oXoXOXoXOXOXoXoXOXoXOXoXOXOXoXoXOXOXoXOXoXoXoXoXOXOXOXoXoXOXoXOXoX", -"oXoXoXOXoXoXOXOXOXoXoXoXOXoXXXoXoXoXoXoXOXoXoXoXoXoXoXOXoXoXOXoXoXOXXX7 N [.OXoXOXoXoXoXOXoXoXoXoXOXoXoXOXoXoXoX& 2 oXoXoXOXoXoXoX=. 4.oXoXOXoXoX^. v oXoXOXOXoXoXoX< & oXoXOXoXOX/. M oXoXoXoXOXoXoX8. +.OXoXoXOXOXoXoXj. =. ^.oXoXoXOXoXoX^. N oXoXoXOXoXoXoX9 @ oXoXoXOXoXoXoXL r.oXoXoXOXOXoXOX@. h oXoXOXoXoXoXoXoXOXoXoXoXoXoXoXOXoXoXoXoXoXoXOXoXOXoXoXoXoXOXoXoXOXoX", -"OXoXOXoXoXOXXXoXoXoXoXoXOXoXOXoXOXoXoXOXoXXXoXOXOXoXOXoXoXoXoXOXoXoXXXj.X 7 ^.XXoXoXOXoXoXOXOXoXOXoXXXoXoXoXXXoX$ 2 OXoXOXoXOXoXOX+. 4.oXXXoXoXoX~. N XXoXOXoXoXOXXX, $ oXOXoXXXoX/. M oXoXoXoXOXoXoX8. +.OXoXOXoXOXoXoXr. g ^.XXoXOXoXoXOX~. X N OXoXOXoXoXOXoX/.^./././.^././.^./././.^.^././.^././.^./.OXoXOXoXoXOXOXO. r.XXoXoXXXoXXXoX@. 8 [.XXXXoXoXoXoXOXoXOXoXOXoXoXoXOXoXOXoXOXoXOXoXoXoXXXXXOXoXOXoXoXoXoXOX", -"oXoXoXoXoXoXoXoXoXoXoXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXoXoXoXoXoXoX+. X ;.oXOXoXoXoXoXoXoXoXoXoXoXOXoXoXoX& < oXoXoXoXoXoXoX=. 4.oXoXoXoXXX^. N oXoXoXoXoXoXoX< # oXoXoXoXOX/. c oXOXoXoXoXoXOXf. +.oXoXoXoXoXoXoXj. ^.oXoXoXoXoXXX~. v oXoXoXoXoXoXoXoXOXoXOXoXoXOXoXoXoXXXoXOXoXoXOXoXOXoXoXoXoXoXoXoXoXoXXXO. j.oXoXoXoXoXoXOX#. X +.XXoXoXoXoXoXOXoXoXoXoXoXoXoXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXoX", -"oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXH N oXoXoXoXoXoXoXoXoXoXoXoXoXoXoX# 2 oXoXoXoXoXoXoX=. 3.oXoXoXoXoX^. N oXoXoXoXoXoXoX< & oXoXoXoXOX/. M oXoXoXoXoXoXoX8. #.oXoXoXoXoXoXoXj. ^.oXoXoXoXoXoX^. N oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXL r.oXoXoXoXoXoXoX*. g +.[.XXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX:. w [.oXoXoXoXoXoXoXoXoXoXoXoXoX& , oXoXoXoXoXoXoX*. 3.oXoXoXoXoX~. v oXoXoXoXoXoXoX< $ oXoXoXoXoX/. x oXoXoXoXoXoXoX8. +.oXoXoXoXoXoXoXr. /.oXoXoXoXoXoX~. N oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXO. j.oXoXoXoXoXoXoX=. @ L B.[.oXoXXX.XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -".XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX.XoXoXoXoXw.@ 4 /.oXoXoXoXoXoXoXoXoXoXoXoX# < oXoXoXoXoXoXoX*. 3.oXoXoXoXoX~. N oXoXoXoXoXoXoX, $ oXoXoXoXoX/. x oXoXoXoX.XoXoX5. +.oXoXoXoXoXoXoXr. /.oXoXoXoXoXoX~. N oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXI r.oXoXoXoXoXoXoX=. * H ~.oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oXoXoXoX.XoXoXoXoXoX.XoXoX.XoXoXoXoX.XoX.XoXoXoXoX.XoXoX.XoXoXoXoXoXoXoX.XoXoXoX/.9 & /.oXoXoX.XoXoXoXoXoXoXoX% < oXoXoXoX.XoXoX*. 3.oXoX.XoXoX~. N oXoXoXoXoX.XoX< # .XoXoXoXoX/. x oXoXoXoXoXoXoX8. +..XoXoXoXoXoXoXr. /..XoXoXoX.XoX~. v oXoX.XoX.XoXoXoX.XoXoXoXoXoX.XoX.XoXoXoX.XoXoXoXoXoX.XoXoXoX.XoXoXoXoXU r.oXoXoXoX.XoXoX+. g B.oXoXoX.XoX.XoXoXoXoXoXoX.XoX.XoXoX.XoXoXoXoXoXoXoXoXoX.XoX.XoXoXoXoX.XoXoX", -"oX.X.XoXoXoXoX.X.XoXoXoXoX.X.XoXoXoXoXoXoXoXoXoXoXoX.XoXoXoX.XoXoXoXoXoXoXoX.XoXoX[.H 5 [..XoXoXoX.XoXoX.XoX.X$ 1 oXoX.XoXoXoXoX*. 3.oXoXoXoXoX~. v .XoXoX.XoXoXoX, & oXoXoX.X.X/. M oX.XoXoX.XoXoX8. +.oXoXoX.XoXoX.Xr. ~.oXoX.XoX.XoX~. v oXoXoXoXoXoX.XoXoXoX.XoXoXoXoXoXoXoX.XoXoXoX.XoX.XoXoX.X.XoXoXoXoX.XoXI r.oX.X.XoXoX.XoX*. U .XoXoXoXoXoXoX.X.XoXoXoXoX.X.XoXoX.XoX.XoXoX.XoX.XoXoX.XoXoX.XoXoX.X.XoX", -".XoXoX.XoX.XoX.X.XoX.XoX.XoXoXoX.X.XoX.X.XoX.X.X.XoXoX.X.X.XoX.X.XoX.X.X.XoXoX.X.XoX.Xr.* l oX.X.XoXoX.X.XoX.XoX& < .XoXoX.X.X.XoX*. 3.oX.XoXoX.X~. v oX.X.XoX.X.XoX< # oX.XoX.XoX/. c oXoXoX.XoX.XoXw. +.oX.X.XoX.X.XoXr. ~..XoXoX.XoXoX~. N .XoX.X.X.XoXoX.X.X.XoX.X.XoX.X.X.XoXoX.X.X.XoX.XoXoX.XoX.XoX.XoX.XoXoXI r..XoXoX.XoXoX.X*. C oX.XoXoX.XoX.XoX.X.XoX.XoXoXoX.XoXoX.X.X.XoX.XoXoX.XoX.XoXoX.X.XoXoX.X", -"oX.X.XoXoX.X.XoX.XoX.XoX.XoX.X.X.XoXoX.XoX.X.XoX.X.XoX.XoXoX.XoXoX.X.XoX.XoX.XoXoX.X.XoX|.H >..X.X.XoX.X.XoXoX.X# < .XoX.XoXoXoX.X*. 3.oXoXoX.XoX~. v .X.XoX.XoXoX.X, # oX.XoXoX.X/. x .X.X.X.XoX.XoX8. +..X.XoX.XoX.X.Xr. /..X.XoX.X.XoX~. v oX.X.XoXoX.XoX.XoX.X.XoXoX.X.XoX.XoX.XoXoX.X.XoX.X.X.XoX.XoX.XoX.XoX.XI r..X.XXXoXoX.XoX*. ;..XoX.X.XoX.XoX.XoXoXoXoX.XoX.XoX.XoXoX.X.X.XoX.X.XoXoX.XoX.XoX.X.XoX", -".XoXoX.X.XoXoX.XoX.X.X.XoX.X.XoXoX.X.XoX.XoXoX.XoXoX.XoX.X.XoX.X.XoXoX.X.X.XoX.X.XoXoX.X.X.X6.# & [.oXoX.X.XoX.X.XoX# , .X.XoX.X.X.XoX*. 3..X.X.XoX.X~. N oXoX.XoX.X.XoX< % .XoX.X.X.X/. x oX.XoX.XoXoX.X8. +.oXoX.XoX.XoXoXr. 8 ~.oXoX.XoXoX.X~. X v .XoXoX.X.XoX.XoX.XoXoX.X.XoXoX.X.X.XoX.X.XoXoX.X.XoX.XoXoX.X.X.X.XoXoXI r..XXX.X.X.XoX.X*. L r.3.K < @ /..X.XoX.XoX.XoX.X.X.X.XoX.X.XoXoX.XoX.XoX.X.XoX.XoX.XoX.X.X.XoXoX.X", -".X.X.X.XoX.X.XoX.XoXoX.X.XoXoX.X.X.XoX.X.XoX.XoX.X.X.X.X.XoX.X.XoX.X.XoXoX.XoX.X.XoX.XoXoX.XoX].x 3.oX.XoX.XoX.XoX.X$ , oX.XoX.XoX.X.X*. 3.oX.XoX.X.X~. v .X.X.X.X.XoX.X, # .X.X.X.X.X/. x .X.X.X.X.X.X.X8. +..X.XoX.X.XoX.Xr. K ~..X.X.X.X.X.X~. v .X.X.X.X.X.X.X.X.X.X.X.X.X.X.XoXoX.XoX.X.XoX.XoX.X.X.X.X.XoXoX.XoX.X.XU r..X.XoX.XoX.XoX;. 3..XoX.X|.c l .XoX.X.X.X.X.X.XoX.X.X.X.XoX.X.XoX.XoX.XoX.X.X.X.X.XoX.XoX.X.X.X.X", -".XoX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XoX.XoX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X3.# q .X.X.X.X.X.X.X.X# X x x l x x x x x l x x x H .X.X.X.X.X.X.X*. 3..X.X.X.X.X~. v oX.XoX.X.X.X.X< & oX.X.X.X.X/. v .X.XoX.XoX.X.X8. 4 x x x l x x l x x l x x 8..X.X.X.X.X.X.Xr.X l. ~.oX.XoX.X.X.X~. v .XoX.XoX.XoX.XoX.XoX.X.XoX.X.X.X.X.X.X.X.X.X.X.XoX.XoX.X.X.X.X.X.X.X.XI w x x x l x x l x x x x x N..X.X.X.X.X.X.X+. 3..X.X.XoX/.. /..X.XoX.XoX.X.X.X.XoX.X.X.X.X.X.X.X.X.X.X.XoX.XoX.X.X.XoX.XoX.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X/.f ]..X.X.X.X.X.X.X# * .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X@. 3..X.X.X.X.X~. v .X.X.X.X.X.X.X, & .X.X.X.X X/. x .X.X.X.X.X.X.X8. O..X.X.X.X|..X.X.X.X.X.X.X.X.X.X.X.X.X.X.Xr. F.8 ~..X.X.X.X.X.X~. v .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XoX.X.XoX.X.X.X.X.X.X.X.X.X.X.X.X.XI w..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X@. 3..X.X.X.X.X8 *..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -"oX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X>.o 3..X.X.X.X.X.X.X# , .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XoX*. 3..X.X.X.X.XN. v .X.X.X.X.X.X.X, # .X.X.X.X.X/. x .X.X.X.X.X.X.X8. O..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.Xe. /.U F..X.X.X.X.X.X~. v .X.X.X.X.X.X.Xx 8 8 8 8 8 9 8 8 8 8 8 9 8 8 8 8 8 9 9 q .X.X.X.X.X.X.XI w..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XoX+. 3..X.X.X.X.XN H .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X~.8 A .X.X.X.X.X.X.X# * .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X*. <..X.X.X.X.XS. v .X.X.X.X.X.X.X< # .X.X.X.X.X/. x .X.X.X.X.X.X.X5. O..X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.Xr. /.M. ~..X.X.X.X.X.XN. v .X.X.X.X.X.X.X4 . @ .X.X.X.X.X.X.XI w..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X*. <..X.X.X.X.XI l .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X|.K g .X.X.X.X.X.X.X& * .X.X.X.X.X.X.X.X.X X.X.X.X.X.X.X.X.X.X.X@. 3..X.X.X.X.X~. v .X.X.X.X.X.X.X3 # .X.X.X.X.XF. c .X.X.X.X X.X.X5. O..X.X.X.X.X.X.X.X.X.X.X.X.X.X X.X.X.X.X Xe. F..X& ~.|..X.X.X.X.XN. v X.X.X.X.X.X.X3 o .X.X.X.X X.X.XU w..X.X.X X.X.X.X.X.X.X.X X.X.X.X.X.X.X X.X@. 3..X.X.X.X.X@. g .X.X.X X.X.X.X.X.X.X X.X.X.X.X X.X.X.X.X X.X.X.X.X.X.X.X.X X.X.X", -".X.X.X X X X.X.X.X.X X X X.X.X.X X.X.X.X X.X.X.X.X.X.X X X X.X.X/.;.;.;.;.;.;.;.;.;.;.;.;.;.:.;.;.;.;.;. X X.X.X@.. * .X.X X.X X.X.X% * X.X.X.X X X X.X.X X.X.X.X.X X.X X X X.X*. <. X.X.X.X XN. v X.X.X.X X.X X3 & .X X X.X XF.. x .X X X.X.X X.X5. O..X X.X.X.X X X.X.X.X X.X X.X.X.X.X.X.X Xr. /..Xv S. X.X.X.X.X.XS. v .X X.X.X.X X.X3 o X.X X.X.X.X.XI w..X.X X.X.X X X X.X.X.X.X.X.X X.X.X.X.X.X+. 3..X X.X.X.X;. 9 .X.X.X X X.X X.X X.X.X.X.X.X.X X X X.X.X.X X.X.X.X X X.X.X.X X.X", -" X X.X.X.X.X.X X X.X.X.X.X.X X X.X X.X X.X.X X.X X X.X.X.X.X.X X8. .X.X.X X X>. ]..X.X.X.X.X X# * .X X X.X.X.X.X.X X.X.X X.X.X.X.X.X.X.X.X;. 3..X X.X.X.XS. N .X X X.X X.X.X4 # .X.X.X.X.XF. c X.X.X X.X.X.Xw. O..X X.X X.X.X.X.X X.X X.X.X.X X.X X X.X.Xe. F. X5. F..X.X X X.X X~. v .X.X.X X.X.X.X4 # .X.X.X.X.X X.XI w.|..X.X X.X.X.X.X.X X.X.X X.X.X X.X X.X.X@. <..X X.X X.X>. 4 .X X.X.X.X.X X.X.X.X X.X X X.X.X.X.X.X X.X.X.X X.X.X.X.X X.X X.X", -".X X X.X X.X X.X X.X.X.X.X X.X.X X.X X.X.X X.X X.X X X.X.X.X.X X5. X.X X.X.X Xc M. X X.X X X.X# , .X.X X X.X X.X X.X.X X.X X X.X|..X X.X X;. <..X.X X.X XS. C .X.X.X.X.X X.X9 # X.X.X X X/. x .X.X.X.X X.X X5. O..X.X X.X X.X.X X.X X.X X.X X.X X.X X X.Xe. /. X].o S. X.X.X.X X.XF. v .X X.X X X.X X3 # X.X.X X.X X XI w. X X.X X.X X.X X.X.X X.X X X.X X.X.X.X.X&. 3..X.X.X.X.X<. 4 X.X X.X.X.X.X X.X X.X X.X X X.X X.X.X X.X X.X X X.X.X X.X X.X X", -" X.X.X X.X X.X X.X X X X.X X X X.X X.X X X.X X.X X.X.X X X X.X X8. .X X.X X.X.XM. 5. X.X X.X.X X# * X X.X.X X.X X.X X X.X X.X X X X.X X X X>. <. X X.X.X|.S. C X X X X X.X X8 * X X X.X XF. v X X X X.X.X X5. +. X.X X X.X X X.X X.X X.X.X X X.X X.X.X Xr. F..X Xg F..X X X.X X.XF. v X.X X.X X X.X4 * .X X X.X X.X XI w..X X X.X X.X X.X X X.X X.X X X.X X X X X*. <. X X X X X<. , X X.X X X X X.X X.X X.X X.X.X X.X X.X X X.X X.X X X.X X X.X X.X", -" X X X.X.X X X X.X X X.X X.X X X X.X X.X X X X X X X.X X X X.X Xw. X.X X X.X.X X2 <. X X X X X.X# * X X.X X X.X.X X X X.X X X X.X X X.X X.X<. <. X.X X X XN. A X X X.X X.X X8 $ X X X X XF. v .X X X.X X X X5. O..X.X X X X.X X X X X X X.X X.X X X X.X.Xe. F. X.X;. S. X X.X.X X XI. v X X.X X X X X4 , X.X X X X.X XI w. X X X|. X X.X X.X X X X.X X X.X.X X X.X@. <..X.X X X X<. , X.X X X.X.X X X.X X X X X.X X X.X.X X X X X X X.X X X.X X X X.X", -".X X X X X X.X X X X X.X X X X.X X.X X X X.X.X X.X X.X X.X X X X5. X X X.X X X Xc ;..X.X X.X X X% & X X X X.X X X X.X X.X X.X X X.X X X X X3. 3. X X X.X XN. H .X.X X X X X Xw # X.X X.X X/. C X X.X X X.X X5. O. X X X.X X.X X.X X.X.X X X X.X X.X X X Xe. F..X XF. S. X.X X X X.X]. v .X X X X X.X.X3 2 X X X.X X.X XI w. X X X.X X X X X.X X.X X X.X X X X.X X.X@. <. X X X.X.X3. * X X X.X X X X.X X X.X X X X X.X X X X.X.X X.X X.X X X.X X.X X X", -" X X X.X.X X X X.X X X X X.X X X X X X X X X.X X X X X X X X X Xw. X.X X X X X XO. @. X X X X X.X% & X X.X X X.X X X X X X X X X.X X X X X Xe. <. X.X X.X XN. D X X X X X.X Xq % X.X X X XF. A X X X X.X X X5. O. X.X X X X X X X X X.X X X X X X X X X Xe. F. X X X4 S. X X X X X X|. v X X X.X.X X X4 8 .X X X X X X XG w. X X X X X X.X X X X X X.X X X X X X X X@. <. X X X X X<. # X.X X X.X X X X X.X X X X.X X X.X X X X X X X X X X X X X.X X X", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X Xe. X X X X X XE.>. O. X X X X X X# , X X X X X X X X X X X X X X X X X X X XM. <. X X X X XM. I X X X X X X Xq # X X X X XF. H X X X X X X X5. O. X X X X X X X X X X X X X X X X X X X Xe. F. X X XK F. X X X X X X Xo v X X X X X X X1 f X X X X X X XI w. X X X X X X X X X X X X X X X X X X X X@. <. X X X X X<. @ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X", -" X X X X X X XQ. X X X X X X X X X X X X X X X X X X X X X X X Xe. X X X X X X X2. K X X X X X X% * X X X X X X X X X X X X X X XQ. X X X XS. ;. X X X X Xb. @. X X X X X X Xk % X X X X XD. S X X X X X X X2. O. X X X X X X X X X X X X X X X X X X X Xe. F. X X Xe. S. X X X X X X X, c X X X X X X X, x X X X X X X XI w. X X X X X X X X X X X X X X X X X X X X@. <. X X X X X<. @ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X", -" X X X X XQ. X X XQ. X X X X XQ. X XQ. X XQ. X X X X X X XQ. X Xb. X X XQ. X X Xw. G X XQ. X X X% & X X XQ. X X X XQ. X X XQ. X X X X X X XI. ;. X X X X Xe. ;. X XQ. X X X Xx # X XQ. X XN. D XQ. X XQ. X X9. O. X X XQ. XE.Q. XQ. X XQ. X X X X XQ. X Xe. D. X X X X$ A.Q. X X XQ. X X8 z Q. X X X X X X% C X XE. X XQ. XG 9. X XQ. X X XE. XE. XQ. X XQ. X X X X X X@. <. X X X X X<. @ XQ. X X X X XQ. X X XQ.Q. X XQ. X X X X XQ. X XQ. X X X X XQ. X", -" X X X X X X X X X X X X X X X X X XQ. X X XQ. X X X X X X X X XN. Q. X X X X X Xb. O. X X X XQ. X# * X XQ. X X X XQ. XE. XQ. XQ. X X XE. X X Xo ;. X XQ. XQ.e. 2. X X X X XQ. XC @ X X X X XM. O. X X X X X X X5. O. X X X X X X X X X X X X X X X X X X X Xe. D. X X X Xc S. XE. X X X X Xf l X X XQ. X XQ.@ D X XE. X X X XI 9. XQ. X X X X X X XQ. X XQ. X X XQ. X X X@. <. X X XQ. X<. @ X X X XQ. X X X XQ. X X X X X X X X X X X X X X X XQ. X X X X X", -" XQ.Q. XQ. XQ. XE.E.Q. XQ. X XQ.Q. X X X XQ. X X XQ. XQ. XQ. XQ.I. I. X XQ. XQ. Xe. @.Q. XQ. X X X% , Q. X X XE.Q. X X XE. X X XQ. X XQ. XE. X X8 &.Q. X X X X2. e.Q. XQ. X X X XS Q. XQ. X Xe. &. XQ. X XQ. X X2. I Q. X XQ.E. XE. XQ. X X X XQ. XQ. XQ. XQ.e. F. XQ. XQ.2. A. X XQ. XQ. X Xv g Q. X X XQ. X X *.Q. X XE. XQ. XG w. X X X XQ.E. XQ. X X X X X XQ. X X XQ. X@. <. XQ.Q. X X<. @ XQ.Q. X X X XQ. X XQ. XQ. X X XE.Q. XQ.Q. XQ. X XQ. X XQ. XQ. X", -"Q. X X X X X X XE. X XQ. XQ. XQ. XQ. XQ. XQ.Q. X XQ. XQ.Q. XQ. X XX F. X X XQ. X X9. *. XQ.Q. X X X# * Q.E.E. XE.Q. XQ. X XQ. X X XQ. X XE.Q. XQ.l @. XQ. XQ. X,. D. XQ.Q. X X XQ.O. E. XQ. XE.q. 1. X XE. X XQ. X9. O. XQ. XQ. X XQ. X XQ. XQ. X XE.Q. XQ. XQ.q. D. XQ. X XT. A. X XQ. X X XQ.O. w Q.E. XQ. XE.E. 9.Q. XQ. XQ. XQ.I 9.Q. X XQ. XQ. X XQ. X XQ. X XE.E.Q. XE. X@. <. X XQ. X X,. @ Q. XQ. X XQ. X X X X XQ. XQ. XQ. XQ. XQ.Q. XQ.Q.Q. XQ. XQ. XQ. X", -" XQ.Q.Q.Q.Q.Q.Q.Q.Q.Q. XQ. XQ. XQ. XQ. XQ. X XQ.Q. XQ. XQ. XQ.Q.E.< N.Q.Q. X XQ. X@. 1.Q. X XQ.Q.Q.# q q g g q q q q q q q q q q g P.Q.Q. XQ. XS D X XQ. XQ.&. E.Q. X XQ.Q.Q.Q.@. I. X XQ.E.2. e.Q. XQ.Q.Q.Q. X2. , q q q q q q q q q q q q f q S XQ. XQ. Xq. D. X XQ. X Xf N.Q.Q. XQ.Q.Q.Q.2. , Q. XQ. XQ.E.F. A. XQ. XQ. XQ. XG 4 q q q q q q q q q q q q q q ;.Q. X XQ.Q.@. ,.Q. XQ.Q.Q.<. @ XQ.Q.Q. XQ.Q.Q.Q.Q. XQ.Q. XQ. XQ. XQ. XQ.Q. X X XQ. XQ. XQ. XQ.", -"Q. XQ. XQ. X XQ. X XQ.Q. XQ. XQ. XQ.Q. XQ. XQ. X XQ. XQ. XQ.Q. X Xf 9. XQ.Q.Q.Q.Q.k M.Q.Q. X XQ. X% F.E. XQ. XQ.2. c Q.Q. X XQ.S 3 XQ.Q. X X XE. X,. M. XQ. XE.@. S. XQ.Q. X XQ. X2. f X XQ. XQ.e. D. XQ.Q.Q.Q.@. A.Q. XQ. XQ. X XM. T. XQ.Q. XQ.9. E.Q.Q.Q. XQ. X XG D Q. XQ. X X@. ,. X XQ.Q. X,. @ Q. X XQ. XQ.Q. XQ. XQ. X XQ. XQ. XQ. XQ. XQ. X XQ.Q. X XQ. XQ.Q.", -"Q.Q.Q. XQ.Q.Q. XQ.Q.Q. XQ. XQ.Q.Q.Q. XQ. XQ.Q.Q. XQ.Q.Q. XQ. XQ. XS S Q. XQ.Q. XN.X P. XQ.Q.Q.Q.Q.# D.E.Q.Q. XQ.P. 3 Q. XQ.Q. X0 c Q. XQ.Q.Q.Q.Q.Q.N. ,.Q.Q.Q.Q.c I.Q.Q. XQ.Q. XQ.9. f Q. XQ.Q.Q.q. D.Q.Q. X XQ.A. N. XQ.Q.Q. XQ.Q.Q.X 5.Q.Q. X XQ.A 8 XQ. X XQ.Q.Q.Q.I D Q.Q.Q.Q.Q.@. ,. XQ. XQ.Q.<. @ Q.Q.Q. XQ. XQ.Q. XQ.Q.Q.Q.Q.Q. X XQ.Q.Q. XQ.Q.Q.Q. XQ.Q.Q.Q.Q. X", -"Q.Q. XQ.Q.Q.Q.Q. XQ.Q.Q.Q.Q.Q. XQ. XQ.Q.Q.Q.Q. XQ.Q.Q.Q.Q.Q. XQ.Q.;. o b.Q.Q.Q.P.8 . o E.Q. XQ.Q.Q. X% D.Q.Q.Q. XQ.Q.3 ;.Q.Q.Q.2. 2.Q.Q. XQ.Q.Q.Q.Q.E.o 8 T.E.Q.M.X 3 Q.Q.Q.Q.Q.Q.Q.Q.2. g Q.Q.Q.Q. Xq. D. XQ.Q. XQ.Q.3 A.Q.Q.Q.Q.Q. XQ.Q.g 1 P.Q.Q.Q.b.. S Q.Q.Q.Q. XQ. XQ.G D XQ.Q.Q.Q.@. ,. XQ.Q. XQ.,. @ Q. XQ.Q.Q.Q. XQ.Q.Q.Q.Q. XQ.Q.Q.Q.Q.Q.Q.Q.Q.Q. XQ. XQ.Q.Q. XQ.Q.", -"Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.A. 0 z k X f Q.Q.Q.Q.Q.Q.Q.% D.Q.Q.Q.Q.Q.Q.O. q C g % E.Q.Q.Q.Q.Q.Q.Q.Q.Q.z , z g X S Q.Q.Q.Q.Q.Q.Q.Q.9. g Q.Q.Q.Q.Q.q. D.Q.Q.Q.Q.Q.Q.A N.Q.Q.Q.Q.Q.Q.Q.Q.O. o l z f 9.Q.Q.Q.Q.Q.Q.Q.Q.G D Q.Q.Q.Q.Q.@. ,.Q.Q.Q.Q.Q.,. @ Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.", -"Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.4 G Q.Q.Q.Q.Q.Q.Q.% Z.E.Q.Q.Q.Q.Q.I. ;.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.1. . N.Q.Q.Q.Q.Q.Q.Q.Q.9. f Q.Q.Q.Q.Q.e. D.Q.Q.Q.Q.Q.Q.q. Z.Q.Q.Q.Q.Q.Q.Q.Q.b. % T.Q.Q.Q.Q.Q.Q.Q.Q.G D Q.Q.Q.Q.Q.@. ,.Q.Q.Q.Q.Q.,. @ Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.", -"Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.D b.Q.Q.Q.Q.Q.Q.Q.% P.Q.Q.Q.Q.Q.Q.Q.C f Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.3 f Q.Q.E.Q.Q.Q.Q.Q.Q.2. g Q.Q.Q.Q.Q.q. D.Q.Q.Q.Q.Q.Q.Q.@ N.Q.Q.Q.Q.Q.Q.Q.Q.Q.0 @.Q.Q.Q.Q.Q.Q.Q.Q.Q.G G Q.Q.Q.Q.Q.@. ,.Q.Q.Q.Q. X,. @ Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.", -"Q.Q.Q.Q.Q.Q.Q.W.Q.Q.Q.Q.Q.Q.Q.W.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.W.Q.Q.P.X 3 Q.Q.Q.Q.W.Q.Q.W.# D.W.Q.W.Q.Q.Q.Q.I.# , P.Q.W.Q.W.Q.W.W.Q.Q.Q.Q.Q.,. X b.Q.Q.Q.Q.Q.Q.Q.Q.Q.9. f Q.Q.Q.Q.Q.q. D.Q.Q.W.Q.W.Q.Q.c Z.Q.Q.W.Q.Q.Q.Q.Q.Q.,. % T.W.Q.Q.Q.Q.Q.W.Q.W.O. D Q.Q.Q.Q.W.@. ,.Q.Q.Q.Q.W.,. @ Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.W.Q.W.Q.Q.Q.Q.Q.Q.Q.Q.", -"W.Q.Q.W.W.Q.Q.Q.Q.W.W.Q.Q.W.Q.Q.W.Q.Q.W.W.Q.Q.W.W.Q.W.Q.Q.W.Q.Q.Q.W.W.C %.W.Q.Q.Q.Q.Q.Q.Q.% D.Q.Q.Q.W.Q.Q.W.W.,. 8 P.Q.Q.Q.Q.Q.Q.Q.Q.W.Q.Q.W.W.Q.f C Q.W.W.Q.Q.W.W.Q.W.Q.2. f Q.Q.Q.W.Q.q. Z.Q.Q.Q.Q.Q.W.Q.,. A.W.Q.Q.Q.Q.W.Q.W.Q.T.4 9.Q.Q.Q.Q.W.Q.Q.Q.Q.Q.F D Q.W.Q.Q.W.@. ,.Q.Q.W.Q.Q.,. @ Q.W.Q.Q.W.Q.W.Q.Q.Q.Q.W.W.Q.W.Q.Q.Q.Q.Q.Q.Q.Q.Q.W.Q.Q.W.W.Q.Q.W.", -"Q.Q.Q.Q.W.Q.W.Q.Q.Q.Q.Q.Q.Q.W.Q.Q.Q.Q.Q.W.Q.Q.W.Q.Q.Q.Q.Q.Q.W.Q.Q.Q.W.I., 8 W.Q.Q.Q.W.W.Q.W.Q.% A.Q.Q.W.Q.Q.Q.Q.W.Q.o. X G T.W.W.Q.W.Q.W.Q.Q.W.Q.Q.Q.Q.Q.Q.D.% , I.Q.Q.Q.Q.Q.Q.Q.W.Q.W.9. f Q.Q.W.Q.W.q. D.Q.W.Q.Q.Q.Q.Q.L. N.Q.Q.Q.Q.W.Q.Q.Q.W.Q.b.o S Q.Q.Q.Q.Q.Q.W.W.Q.Q.Q.F D Q.Q.W.W.Q.@. ,.Q.Q.Q.W.Q.,. @ W.Q.Q.W.Q.Q.W.Q.W.Q.W.Q.Q.Q.W.Q.W.Q.W.Q.Q.W.Q.Q.Q.Q.Q.Q.Q.Q.Q.W.", -"Q.W.W.Q.Q.Q.W.Q.W.Q.W.Q.W.Q.Q.W.Q.W.W.Q.Q.Q.W.Q.W.Q.W.Q.W.Q.Q.W.W.Q.Q.Q.b.X # N.Q.Q.W.Q.W.Q.Q.Q.W.% D.W.Q.Q.Q.W.W.Q.Q.Q.Q.D X C D.W.Q.Q.Q.Q.W.Q.Q.Q.Q.Q.Q.Q.W.Q.W.W.Q.0. X b.Q.Q.W.Q.W.W.Q.W.Q.W.Q.1. g W.W.Q.W.Q.q. Z.Q.Q.Q.W.W.Q.W.Q.0 Z.Q.W.W.Q.W.Q.Q.W.Q.Q.W.@. c W.W.Q.W.Q.W.Q.Q.Q.W.W.Q.G D W.Q.Q.Q.W.@. ,.Q.W.Q.Q.W.,. @ W.Q.Q.W.Q.W.Q.Q.W.W.Q.W.Q.W.Q.Q.Q.Q.W.Q.Q.W.Q.W.Q.W.W.Q.W.Q.W.Q.", -"Q.Q.Q.W.W.Q.W.Q.W.Q.W.W.W.Q.Q.Q.Q.W.Q.W.W.Q.W.Q.W.Q.W.W.W.Q.Q.W.W.Q.Q.Q.Q.9.@ o b.W.Q.W.Q.Q.W.Q.Q.W.Q.# D.Q.W.W.Q.W.Q.W.Q.W.W.Q.%.o o z ,.I.W.W.Q.Q.W.W.W.Q.W.Q.W.Q.Q.Q.W.Q.W.Q.W.W.Q.7.X 1.W.Q.W.W.Q.W.Q.W.Q.Q.W.Q.7. f W.Q.W.W.Q.q. D.W.Q.W.W.Q.W.W.Q.O. A.W.W.Q.W.Q.W.Q.Q.W.Q.Q.W.@. c T.Q.Q.W.Q.W.W.Q.Q.W.Q.Q.W.G D Q.W.W.Q.W.@. ,.W.Q.W.W.Q.,. @ Q.Q.W.Q.Q.Q.W.W.Q.W.Q.W.W.Q.W.W.W.Q.Q.W.Q.W.W.Q.Q.W.Q.W.W.Q.W.Q.", -"W.W.W.Q.Q.W.W.W.Q.W.W.Q.Q.W.W.W.W.Q.W.Q.Q.W.W.W.Q.W.W.Q.Q.W.W.Q.Q.W.W.W.W.W.m.% , m.Q.W.W.W.W.W.Q.W.W.W.W.% Z.W.W.Q.Q.W.W.W.W.Q.W.W.Q.b.1 1 T.W.W.Q.W.Q.W.W.Q.W.Q.W.Q.W.W.W.W.W.Q.W.Q.W.Q.Q.W.W.m.# o 1.W.Q.W.W.Q.Q.W.W.Q.W.W.W.W.7. f Q.W.Q.Q.W.0. Z.Q.Q.W.Q.W.Q.W.W.m. A.W.Q.W.Q.W.Q.W.W.W.W.W.Q.W.%. o.W.Q.W.W.W.W.Q.Q.W.W.Q.W.W.W.G D W.Q.W.W.W.@. ,.W.W.Q.W.W.,. @ W.W.W.W.W.W.W.Q.W.Q.W.Q.Q.W.W.Q.W.W.W.Q.Q.W.Q.W.W.Q.W.Q.Q.W.W.W.", -"W.W.W.W.W.Q.W.Q.W.Q.W.W.W.W.Q.W.W.W.W.W.W.Q.W.Q.W.Q.W.W.W.W.W.W.W.W.Q.W.Q.W.W.L.z k L.W.W.W.W.Q.W.W.W.W.Q.W.Q.% Z.W.Q.W.W.W.W.Q.W.W.Q.W.W.W.W.,.@ T.W.W.W.W.W.W.W.W.W.Q.W.W.Q.W.Q.W.W.W.W.W.W.W.W.W.W.Q.L.k 1 m.W.W.Q.W.Q.W.W.W.W.W.W.W.Q.W.7. f W.W.Q.W.W.0. Z.W.W.Q.W.W.Q.W.W.W., Z.Q.W.W.W.W.W.W.Q.W.W.Q.W.Q.W.A.4 , m.W.Q.W.Q.W.Q.W.W.W.W.W.W.W.Q.W.G D W.Q.W.Q.W.@. ,.Q.W.Q.W.Q.,. @ W.W.Q.W.W.Q.W.W.W.W.Q.W.W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Q.", -"Q.W.Q.W.W.W.W.W.W.W.Q.W.Q.W.W.W.W.Q.W.Q.W.W.W.W.W.W.Q.W.Q.W.Q.W.Q.W.W.W.W.W.W.Q.W.1., 8 9.Q.W.W.Q.W.Q.W.W.W.Q.W.W.W.W.# D.W.W.W.W.Q.W.Q.W.Q.W.W.W.Q.W.Q.L.o.1 m.W.Q.W.Q.Q.W.Q.W.W.W.W.Q.W.W.W.W.W.Q.W.Q.W.Q.W.Q.Q.W.W.W.1.3 A T.Q.Q.W.W.W.W.W.Q.W.Q.W.Q.Q.W.W.7. f W.Q.W.W.Q.q. Z.W.W.W.W.Q.W.W.W.Q.A Z.W.W.W.Q.Q.W.W.W.Q.W.W.W.W.W.W.T.D o o F L.Q.W.W.W.W.W.Q.W.Q.Q.W.Q.W.W.W.W.G D W.W.W.Q.W.o. ,.W.W.W.W.W.,. @ W.Q.W.W.W.W.Q.Q.W.Q.W.W.W.W.Q.Q.Q.W.Q.W.W.Q.W.Q.W.Q.W.Q.W.Q.W.W.", -"W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Q.W.,.8 X k 9.W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.Q.% Z.Y.W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.0.o.k @ 3 m.W.W.W.W.W.W.W.W.W.W.W.W.Q.W.W.W.Q.W.W.Q.W.Q.W.Q.W.W.W.W.W.1.f c m.W.W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.W.7. f Q.W.Q.W.W.0. Z.W.W.Q.W.W.W.W.W.W.9. A.W.W.W.Q.W.W.W.W.W.Q.W.W.W.W.W.W.W.L.o.% @ A L.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.O. D W.W.W.W.W.@. ,.W.W.W.W.W.,. @ W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.W.W.W.Q.W.", -"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.m.O.0 X X f o.Z.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.m.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.T.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.T.Z.m.o X % 3 8 8 8 8 8 8 8 S W.W.W.W.W.R.W.Q.R.W.R.W.R.W.W.W.W.W.W.W.L.o.f @ 0 @.L.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.L.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.m.W.W.W.W.W.I.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.R.Q.W.W.W.W.W.W.W.W.W.m.m.m.n.n.m.m.m.m.m.m.m.m.m.m.m.m.m.T.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.0.A 1 k ,.T.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.D.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.Z.W.W.W.W.W.L.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.L.W.W.W.W.W.L.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.Z.W.W.W.W.W.W.W.W.W.W.W.W.W.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.", -"W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.L.m.%.S k f 8 1 , , 3 8 f A %.0.T.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.% k W.W.W.W.W.W.W.Y.W.W.W.W.W.W.Y.Q.Y.W.W.W.W.W.W.W.m.%.D z 8 8 1 1 , 8 8 k A o.0.I.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.Q.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Z.7.%.A f q 8 1 , , 8 f f C %.m.T.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.R.W.W.W.W.W.W.W.W.", -"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.Y.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.1 k W.W.W.W.W.W.Y.Q.W.W.R.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.Y.W.W.W.W.Y.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.Q.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.Y.Q.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.Y.W.Y.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.", -"W.W.W.R.W.W.W.W.W.W.W.W.R.W.W.R.W.W.W.R.W.W.R.W.W.W.W.W.W.R.W.R.W.W.W.W.W.R.W.Y.Y.W.W.W.W.Y.W.W.W.R.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.R.W.W.R.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.Y.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.8 k W.Y.W.Y.W.W.W.W.R.W.W.R.R.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.W.W.Y.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.W.W.Y.W.Y.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.R.W.Y.W.W.W.W.W.W.W.Y.W.Y.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.W.W.W.W.W.W.Y.W.Y.W.W.R.W.W.R.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.Y.W.W.W.W.Y.W.W.W.W.W.W.Y.W.W.W.Y.W.W.W.W.Y.W.W.W.W.W.W.W.W.Y.W.W.W.W.Y.W.W.W.Y.W.W.W.W.W.W.W.W.Y.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.Y.W.W.Y.Y.W.W.Y.W.W.W.W.W.W.W.W.W.W.R.W.W.W.R.W.W.W.W.R.W.W.R.W.W.W.R.R.W.W.W.W.R.W.W.W.W.R.W.W.R.W.W.W.", -"R.W.W.R.W.R.R.W.R.R.R.W.R.W.W.R.R.W.W.R.W.R.W.W.R.R.R.W.R.W.W.R.W.R.R.W.R.W.W.W.Y.W.R.W.W.W.W.W.R.W.W.Y.W.Y.R.W.Y.W.W.W.W.W.W.W.W.Y.W.Y.Y.W.W.Y.Y.W.W.W.W.R.R.W.Y.W.W.Y.W.W.Y.W.Y.W.W.W.W.Y.Y.W.Y.W.Y.W.W.W.W.W.Y.W.W.Y.W.W.Y.W.Y.W.W.W.W.Y.Y.W.Y.W.W.W.W.W.W.W.W.Y.Y.W.W.Y.W.W.Y.W.W.Y.W.Y.Y.W.Y.W.Y.R.k k W.W.W.W.Y.W.Y.W.W.R.Y.W.W.W.R.W.Y.W.W.W.W.W.W.W.W.Y.Y.W.Y.W.Y.W.Y.W.W.W.W.W.W.W.W.W.Y.W.W.Y.Y.W.W.Y.W.W.Y.W.W.W.W.R.R.W.W.W.W.R.Y.W.W.W.W.W.W.Y.W.Y.Y.W.W.Y.W.W.Y.W.Y.W.W.W.W.W.W.Y.Y.W.W.W.Y.R.W.W.W.W.W.Y.Y.W.Y.W.W.W.W.Y.Y.W.Y.W.W.Y.Y.W.Y.W.W.W.W.W.W.Y.Y.W.W.W.W.W.W.Y.Y.W.W.Y.Y.W.Y.W.W.W.W.W.W.W.W.Y.Y.W.R.W.Y.W.Y.W.Y.W.R.W.W.R.W.W.W.Y.Y.W.Y.W.W.W.W.W.Y.W.W.Y.Y.W.Y.W.W.W.W.W.W.Y.Y.W.Y.W.Y.W.W.W.W.W.W.W.R.W.W.W.R.W.W.Y.W.W.Y.W.W.W.Y.W.W.W.W.W.W.Y.W.W.W.Y.W.Y.Y.W.Y.W.W.W.W.W.W.Y.W.W.W.Y.W.Y.Y.W.W.Y.W.W.Y.W.W.W.W.Y.W.W.Y.W.W.W.Y.W.W.W.W.W.W.W.Y.W.W.Y.Y.W.W.Y.Y.W.Y.W.W.W.W.W.W.W.W.W.W.Y.W.W.Y.W.W.Y.R.W.W.R.R.R.W.W.W.R.R.W.R.W.W.R.R.R.W.W.W.R.R.R.W.W.R.W.R.W.R.W.W.R.R.R.", -"R.R.W.W.R.R.R.R.W.W.R.R.R.R.W.W.R.R.W.W.R.R.R.R.W.W.R.R.R.R.W.W.R.R.R.R.W.W.R.Y.W.W.R.W.Y.Y.W.Y.R.W.W.W.Y.Y.W.W.W.W.Y.Y.Y.W.W.Y.Y.W.W.Y.W.R.W.R.W.R.W.R.R.R.R.W.Y.W.W.Y.Y.W.W.Y.W.Y.Y.W.W.W.W.W.W.Y.Y.W.W.Y.Y.W.Y.W.W.Y.Y.W.W.Y.W.Y.Y.W.W.W.Y.W.W.Y.Y.W.W.Y.Y.W.R.W.W.Y.Y.W.W.Y.Y.W.W.Y.W.W.R.W.W.W.R.R.O. z R.R.Y.W.W.W.W.R.W.Y.W.W.R.R.W.R.W.W.Y.Y.Y.W.W.Y.W.Y.W.W.W.W.Y.W.W.W.Y.Y.Y.W.W.Y.Y.Y.W.W.W.Y.W.W.W.W.Y.W.W.W.Y.Y.R.R.R.W.Y.Y.W.W.W.W.Y.Y.Y.W.W.W.Y.Y.W.W.W.Y.W.W.W.Y.Y.W.W.Y.Y.W.R.W.W.Y.Y.W.R.W.W.Y.Y.W.W.W.Y.W.W.Y.Y.W.W.W.W.W.Y.W.W.W.W.W.Y.W.W.Y.Y.W.W.W.Y.W.W.Y.Y.W.W.W.W.W.W.W.W.W.W.Y.Y.W.W.Y.W.W.W.W.W.Y.Y.W.W.R.W.Y.W.R.W.R.R.R.R.R.Y.W.W.Y.Y.W.W.Y.Y.W.Y.W.W.W.W.W.Y.W.W.Y.Y.W.W.W.W.W.W.Y.Y.W.W.Y.Y.W.R.R.W.R.R.R.R.R.W.W.Y.W.W.W.Y.Y.W.W.Y.Y.Y.W.W.W.Y.Y.W.W.W.Y.W.W.W.W.Y.Y.Y.W.W.W.Y.W.W.W.Y.Y.W.W.W.Y.W.W.W.W.Y.Y.W.W.Y.W.W.W.Y.Y.W.W.Y.Y.Y.W.W.Y.Y.W.W.Y.Y.W.W.W.W.W.Y.W.W.Y.Y.W.Y.W.W.Y.Y.W.W.Y.Y.W.Y.W.W.R.R.R.R.W.R.R.W.R.R.W.W.R.R.R.R.W.R.R.W.R.W.R.R.R.W.R.W.R.R.R.W.R.W.R.", -"W.R.R.R.R.W.W.R.R.R.R.W.W.R.R.R.W.R.R.R.R.W.W.R.R.R.R.W.W.R.R.R.R.W.W.R.R.R.R.W.W.Y.W.Y.W.W.R.W.W.Y.R.R.W.W.W.Y.Y.W.W.W.W.Y.Y.W.W.Y.W.W.R.W.Y.W.Y.W.R.R.W.W.R.R.W.W.Y.W.W.Y.W.Y.W.W.Y.W.Y.W.Y.Y.W.W.W.W.Y.W.W.Y.W.W.Y.W.W.Y.W.Y.W.W.Y.W.Y.W.W.Y.W.W.W.W.Y.W.W.Y.W.Y.W.W.W.Y.Y.W.W.W.Y.W.Y.W.R.R.W.Y.R.Y.m. k W.R.W.R.W.Y.Y.W.R.W.R.R.W.R.R.R.W.Y.W.W.W.Y.Y.W.Y.W.W.Y.Y.W.W.R.Y.W.W.W.W.Y.Y.W.W.W.Y.W.Y.W.W.Y.Y.W.W.Y.W.Y.W.W.R.W.W.Y.W.W.Y.W.W.Y.W.W.W.Y.Y.W.W.W.W.Y.Y.W.W.Y.W.W.W.W.Y.W.W.Y.R.W.R.W.W.Y.W.Y.W.W.W.Y.Y.W.W.Y.W.W.W.W.Y.Y.W.Y.W.W.Y.Y.W.Y.W.Y.W.W.W.Y.Y.W.W.Y.W.W.W.W.Y.Y.W.Y.Y.W.Y.Y.W.W.W.W.Y.W.Y.W.Y.Y.W.W.W.W.Y.R.W.W.Y.W.R.W.Y.W.W.R.W.R.W.W.W.W.Y.W.W.Y.W.W.Y.Y.W.Y.W.Y.W.W.Y.W.Y.W.Y.Y.W.W.W.W.Y.W.W.Y.W.R.R.R.W.R.R.R.Y.W.W.Y.W.Y.W.W.W.Y.W.W.W.Y.Y.W.W.W.Y.W.Y.W.W.Y.W.Y.W.W.W.Y.Y.W.W.Y.Y.W.W.W.W.Y.Y.W.W.Y.Y.W.W.W.Y.W.W.Y.W.Y.W.W.Y.W.W.W.W.Y.Y.W.W.W.Y.W.W.W.Y.Y.W.Y.W.Y.W.W.W.Y.W.Y.W.W.W.Y.W.Y.W.W.Y.W.R.W.R.R.R.R.W.R.R.W.R.R.R.R.W.W.R.R.W.R.R.R.W.R.W.R.R.R.W.R.W.R.R.R.W.R.", -"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.R.R.R.R.R.R.Y.W.Y.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.o. k R.R.R.R.R.R.R.R.R.R.R.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.T.R.R.R.R.R.R.Y.Y.W.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.W.R.R.R.R.R.W.R.R.R.R.R.W.R.R.R.T.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.W.R.R.R.R.R.W.R.R.R.R.R.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.R.R.R.R.R.R.Y.W.Y.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.", -"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.W.Y.W.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.7.8 k R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.W.Y.W.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.W.Y.R.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.", -"R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.R.R.Y.R.R.Y.R.R.R.R.Y.R.R.Y.R.R.R.R.Y.R.R.R.Y.R.R.Y.R.R.R.Y.R.R.Y.R.R.R.R.R.Y.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.R.R.R.R.R.Y.R.R.Y.R.R.R.R.R.Y.R.Y.W.Y.Y.m.o.C k f 8 1 , 1 , , , , , , , , , , , , , 1 C R.R.U.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.R.R.Y.R.R.R.Y.R.R.Y.R.R.R.R.R.R.R.R.Y.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.U.U.R.R.R.R.Y.R.R.R.R.R.R.R.Y.R.R.Y.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.U.R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.R.R.Y.R.R.Y.R.R.R.R.Y.R.R.Y.R.R.R.R.Y.R.R.R.Y.R.R.Y.R.R.R.R.R.R.Y.R.R.R.R.R.Y.Y.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.", -"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.U.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.Y.Y.R.R.R.R.R.Y.R.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.Y.R.R.R.Y.R.R.R.R.R.Y.Y.R.R.R.R.R.R.Y.Y.Y.Y.R.R.U.R.R.Y.Y.Y.Y.Y.W.Y.R.R.R.R.Y.Y.Y.W.Y.Y.Y.Y.R.R.R.R.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.Y.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.Y.Y.R.R.R.R.Y.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.R.R.Y.R.R.R.R.R.Y.Y.R.R.R.R.R.R.Y.Y.R.R.R.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.U.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Y.R.Y.Y.R.R.R.R.R.R.Y.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.", -"R.R.R.R.R.U.R.U.R.R.R.R.R.U.R.U.R.R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.U.U.R.R.Y.R.Y.Y.Y.R.Y.R.R.R.Y.R.Y.R.Y.Y.Y.R.Y.Y.Y.R.Y.R.Y.Y.Y.T.R.R.R.Y.R.Y.R.Y.R.R.Y.R.R.R.Y.R.U.R.R.R.R.R.R.R.R.U.R.R.U.R.U.R.R.U.U.R.R.R.R.U.R.U.R.U.R.R.R.R.U.R.R.U.R.R.R.U.U.R.R.R.U.R.U.R.Y.R.Y.Y.Y.R.Y.Y.Y.R.R.Y.R.Y.R.Y.R.R.R.R.Y.W.Y.R.R.U.R.R.R.R.R.R.Y.Y.Y.Y.Y.W.R.R.R.R.R.R.Y.R.R.R.R.R.R.R.U.R.U.R.R.R.R.R.U.R.R.R.R.R.R.R.R.R.U.U.R.R.R.R.R.R.U.U.U.R.R.R.R.U.R.R.U.R.R.R.R.U.R.R.R.R.Y.Y.R.Y.R.R.R.R.Y.R.Y.Y.Y.R.Y.R.Y.R.R.R.Y.Y.R.R.Y.R.Y.Y.Y.T.R.R.R.R.Y.R.R.R.Y.R.R.R.Y.R.Y.R.R.U.R.U.R.R.R.R.U.R.R.U.R.R.R.U.U.R.U.R.U.R.U.R.R.U.R.R.R.R.R.U.R.R.U.R.R.R.U.R.U.R.U.R.R.R.R.R.Y.R.Y.Y.Y.R.Y.Y.Y.R.R.Y.R.Y.R.Y.R.Y.Y.R.R.R.Y.R.R.U.R.R.R.R.Y.R.R.R.R.U.R.R.R.U.U.R.U.R.R.R.R.R.R.R.U.U.R.R.R.R.U.R.R.U.R.R.R.R.R.R.R.R.R.U.R.U.R.R.R.R.R.U.R.U.R.R.R.R.U.R.R.R.R.R.R.R.U.R.R.R.U.U.R.R.Y.R.Y.Y.Y.R.Y.R.R.R.Y.R.Y.R.Y.Y.Y.R.Y.Y.Y.R.Y.R.Y.Y.Y.T.R.Y.R.R.R.Y.R.Y.R.R.Y.R.Y.Y.R.Y.U.R.R.R.R.R.R.R.U.R.R.R.U.R.Y.R.R.Y.U.R.R.R.U.R.R.R.U.U.R.U.U.R.U.R.U.R.R.R.R.U.R.U.U.R.U.R.U.R.", -"R.U.R.U.Y.Y.R.R.R.U.R.U.Y.Y.R.R.R.U.R.U.R.Y.R.Y.R.U.R.U.R.Y.R.Y.R.R.Y.R.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.R.Y.Y.R.U.R.R.R.Y.R.Y.R.R.Y.R.R.R.R.U.R.R.R.Y.Y.R.R.U.U.R.U.U.R.Y.R.Y.R.Y.Y.R.Y.Y.Y.R.R.U.R.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.Y.R.U.R.Y.Y.Y.W.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.R.R.R.U.Y.Y.U.R.Y.Y.R.U.R.U.Y.Y.R.R.R.U.R.U.Y.Y.R.R.R.U.R.U.Y.R.R.Y.R.U.R.U.Y.R.R.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.Y.R.U.R.U.R.Y.R.Y.R.Y.Y.R.R.R.Y.R.R.U.R.Y.R.R.Y.R.U.R.R.R.U.R.Y.Y.Y.Y.R.R.R.R.Y.R.U.R.U.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.U.R.Y.Y.U.R.Y.R.R.R.R.Y.R.U.R.U.Y.Y.R.R.Y.R.U.R.U.R.Y.R.Y.R.Y.Y.R.U.R.U.Y.Y.R.R.R.U.R.U.Y.Y.R.R.R.U.R.U.R.Y.R.Y.R.U.R.U.R.Y.R.Y.R.R.Y.R.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.R.R.Y.R.Y.R.Y.U.R.U.R.R.R.Y.R.Y.R.R.Y.Y.R.R.R.U.R.R.R.Y.Y.R.R.R.R.R.R.U.R.R.Y.R.U.Y.R.R.R.R.Y.R.R.U.R.", -"Y.Y.U.R.Y.Y.Y.Y.Y.Y.U.R.R.Y.U.R.Y.Y.R.U.Y.Y.Y.Y.Y.Y.R.U.Y.Y.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.U.R.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.R.Y.Y.Y.Y.R.R.R.R.R.R.U.R.Y.Y.Y.Y.U.R.Y.Y.Y.R.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.U.R.R.U.R.R.R.Y.Y.Y.Y.Y.U.R.Y.Y.Y.Y.Y.Y.U.R.R.R.R.U.Y.Y.R.U.Y.Y.Y.Y.Y.Y.R.U.Y.Y.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.R.R.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.Y.Y.Y.Y.U.R.U.R.R.U.R.R.Y.Y.Y.Y.Y.Y.Y.Y.R.U.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.R.Y.R.Y.Y.Y.Y.Y.Y.Y.R.U.R.U.Y.Y.Y.Y.Y.Y.R.U.R.R.U.R.Y.Y.Y.Y.Y.Y.U.R.Y.Y.Y.Y.Y.Y.U.R.R.Y.U.R.Y.Y.R.U.Y.Y.Y.Y.Y.Y.R.U.Y.Y.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.Y.R.U.U.R.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.R.Y.Y.Y.Y.U.R.U.R.R.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.", -"Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.R.U.R.R.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.R.U.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.U.Y.Y.Y.Y.Y.Y.U.R.U.R.R.U.Y.Y.Y.Y.Y.R.Y.Y.Y.U.R.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.U.R.U.R.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.U.R.U.R.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.R.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.U.R.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.Y.Y.Y.Y.R.U.R.R.U.R.U.R.Y.Y.Y.Y.Y.Y.R.R.U.R.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.U.R.Y.Y.Y.Y.Y.Y.U.R.U.R.R.U.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.R.U.R.R.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.R.Y.Y.Y.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.R.U.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.U.Y.Y.Y.R.R.U.R.U.R.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.R.", -"Y.Y.R.U.R.R.U.R.U.R.U.U.R.U.R.U.Y.Y.R.U.R.U.R.U.Y.U.Y.Y.Y.Y.U.R.Y.Y.U.R.U.U.R.U.Y.Y.U.Y.U.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.R.U.U.R.R.U.Y.Y.U.R.U.U.R.U.R.U.R.U.R.U.R.U.R.U.U.R.Y.Y.Y.Y.Y.Y.Y.Y.R.R.U.U.R.R.U.R.R.U.R.U.R.U.U.R.R.U.U.R.Y.Y.U.R.U.U.R.U.Y.Y.U.Y.U.Y.Y.Y.U.Y.U.Y.Y.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.Y.R.U.R.R.R.U.R.U.R.U.R.U.Y.Y.U.R.U.U.R.Y.R.U.U.R.U.R.U.R.U.R.R.U.Y.Y.Y.Y.Y.Y.R.U.R.R.U.R.R.U.R.R.U.R.U.R.Y.Y.U.R.U.R.U.R.Y.U.Y.Y.Y.Y.R.U.Y.Y.R.U.R.U.R.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.Y.Y.Y.Y.Y.U.Y.Y.Y.Y.Y.Y.U.R.R.U.U.R.R.U.Y.Y.U.R.U.R.Y.Y.R.U.R.R.U.R.U.R.R.U.U.R.Y.Y.Y.Y.Y.U.R.Y.U.R.U.U.R.U.R.U.U.R.U.U.U.R.R.U.U.R.R.U.Y.Y.R.U.R.U.R.U.Y.Y.U.Y.U.Y.Y.Y.U.Y.U.Y.Y.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.R.U.U.R.R.U.U.R.Y.Y.U.R.U.R.U.R.R.U.R.R.U.R.U.R.R.U.U.R.Y.Y.Y.Y.Y.Y.R.U.R.R.U.R.U.R.U.U.R.U.R.U.Y.Y.R.U.R.U.R.U.Y.U.Y.Y.Y.Y.U.R.Y.Y.U.R.U.U.R.U.Y.Y.U.Y.U.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.R.R.U.U.R.R.U.Y.Y.U.R.U.U.R.U.R.U.R.R.U.R.U.R.Y.Y.R.U.Y.Y.Y.Y.Y.Y.Y.Y.U.R.U.R.U.U.R.U.U.R.U.R.R.U.U.R.R.U.U.R.Y.Y.U.R.U.R.U.R.", -"U.U.U.R.U.U.U.U.R.U.U.R.U.R.U.U.U.U.U.U.U.R.R.U.Y.Y.Y.U.Y.U.U.R.Y.U.R.U.U.R.U.R.Y.Y.Y.Y.U.Y.Y.Y.Y.Y.U.Y.U.Y.Y.U.U.Y.Y.U.Y.U.Y.U.R.U.U.R.R.U.U.R.Y.U.R.U.U.R.U.R.U.U.U.R.R.U.U.R.Y.R.U.U.U.Y.U.Y.Y.U.Y.U.U.U.U.R.U.U.U.U.U.U.U.R.U.R.U.U.U.R.U.U.Y.U.R.U.U.R.Y.R.Y.Y.Y.Y.U.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.Y.U.U.Y.U.Y.U.Y.U.R.U.U.U.R.U.R.U.R.U.R.Y.Y.R.U.U.R.Y.Y.U.R.R.U.U.U.R.U.R.U.U.R.U.U.Y.Y.U.U.U.R.U.U.R.U.U.R.U.U.U.U.U.R.U.Y.U.R.R.U.U.U.Y.Y.Y.U.U.U.U.U.Y.U.U.R.Y.U.U.Y.U.Y.U.Y.Y.U.U.Y.Y.Y.Y.Y.Y.U.U.U.Y.Y.Y.U.Y.U.U.Y.R.U.U.R.R.U.U.R.Y.U.R.U.R.U.U.U.U.R.U.U.U.U.R.U.U.R.U.U.U.Y.U.Y.Y.U.U.Y.R.U.U.R.U.R.R.U.R.U.U.R.R.U.U.R.R.U.U.R.U.Y.U.U.U.R.R.U.Y.Y.Y.Y.U.Y.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.U.Y.Y.U.U.Y.Y.U.U.Y.U.Y.U.R.U.U.U.R.U.U.U.Y.U.R.R.U.U.U.U.R.U.U.R.U.U.R.U.U.R.U.Y.U.Y.U.U.U.U.R.U.U.U.U.R.U.U.R.U.R.U.U.U.U.U.U.U.R.R.U.Y.Y.Y.U.Y.U.U.R.Y.U.R.U.U.R.U.R.Y.Y.Y.Y.U.Y.Y.Y.Y.Y.U.Y.U.Y.Y.U.U.Y.Y.U.Y.U.Y.U.R.U.U.R.R.U.U.R.Y.U.R.U.U.R.R.U.U.R.U.U.U.U.R.U.Y.R.U.R.U.Y.U.Y.U.Y.U.U.U.R.R.U.U.R.R.U.R.U.R.U.U.R.U.U.U.R.U.U.U.Y.U.R.R.U.U.U.", -"U.R.U.U.U.R.R.U.R.U.U.U.U.R.U.R.U.R.U.R.U.R.U.U.Y.U.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.Y.Y.Y.Y.U.Y.Y.Y.U.U.U.Y.U.U.Y.U.U.Y.U.U.Y.Y.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.R.R.U.U.U.R.U.U.U.U.R.U.Y.Y.U.U.R.U.U.U.R.R.U.U.R.R.U.U.R.R.U.U.U.U.R.U.U.U.R.U.U.U.U.U.R.U.U.Y.U.Y.U.Y.Y.U.Y.U.Y.U.Y.U.Y.U.Y.U.Y.U.Y.Y.Y.Y.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.R.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.Y.U.Y.U.U.R.U.U.U.R.U.U.U.U.U.U.R.U.U.U.U.U.R.U.R.U.U.R.Y.U.U.Y.U.R.U.R.U.Y.U.U.U.R.U.U.U.Y.U.Y.Y.U.Y.Y.Y.Y.U.U.U.Y.U.U.Y.Y.U.Y.U.U.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.R.Y.U.Y.U.U.R.U.U.R.U.U.R.U.R.U.U.R.U.U.R.U.U.R.U.U.U.U.U.Y.U.U.R.U.U.U.U.Y.U.Y.U.Y.Y.U.Y.U.Y.U.Y.U.Y.U.Y.Y.U.U.Y.Y.U.U.Y.U.Y.U.Y.U.Y.U.Y.U.U.U.R.U.U.U.R.U.U.R.U.R.U.U.R.U.U.U.U.U.U.R.U.U.R.R.U.U.U.U.Y.U.R.U.U.U.R.R.U.R.U.U.U.U.R.U.R.U.R.U.R.U.R.U.U.Y.U.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.Y.Y.Y.Y.U.Y.Y.Y.U.U.U.Y.U.U.Y.U.U.Y.U.U.Y.Y.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.Y.Y.U.U.U.U.U.R.U.U.U.U.U.U.U.R.U.U.U.U.U.U.R.U.U.U.R.U.U.R.U.R.U.U.R.", -"U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.R.U.U.R.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.Y.U.Y.U.Y.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.R.U.U.U.U.U.U.R.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.Y.U.U.Y.U.Y.U.U.U.U.U.U.Y.R.U.U.U.R.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.R.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.Y.U.U.U.U.U.Y.U.U.U.Y.Y.U.U.U.U.Y.U.U.U.U.U.R.U.U.U.U.U.U.U.R.U.U.R.U.U.R.U.U.U.U.R.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.Y.U.U.U.U.U.U.U.Y.U.U.Y.U.Y.Y.U.U.U.Y.U.U.U.U.U.U.Y.U.U.U.R.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.R.U.U.R.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.Y.U.Y.U.Y.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.R.U.U.U.R.U.U.U.U.R.U.U.U.U.U.U.U.U.Y.U.R.U.U.U.U.U.U.U.R.U.U.U.U.U.U.R.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.", -"U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.Y.U.U.Y.U.U.U.U.U.U.R.U.U.U.U.U.U.U.Y.U.U.U.Y.U.U.U.U.U.U.Y.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.Y.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.Y.U.U.U.Y.U.U.U.Y.U.U.U.U.U.U.U.U.Y.U.U.Y.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.R.U.U.Y.U.U.Y.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.Y.U.Y.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.Y.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.Y.U.U.U.Y.U.U.U.Y.U.U.U.U.U.U.U.Y.U.Y.U.U.Y.U.Y.U.U.U.Y.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.Y.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.Y.U.U.Y.U.U.U.U.U.U.R.U.U.U.U.U.U.U.Y.U.U.U.Y.U.U.U.U.U.U.Y.U.U.U.U.U.Y.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.R.U.Y.U.U.U.R.U.U.U.U.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.", -"U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.Y.U.Y.U.U.U.U.U.Y.U.U.U.R.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.Y.U.Y.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.", -"U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.", -"U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.K.U.U.U.U.K.U.U.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.K.U.U.U.K.U.U.U.U.K.U.U.U.U.K.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.K.U.U.U.U.K.U.U.U.U.K.U.K.U.U.U.U.U.K.U.U.K.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.K.U.U.U.U.K.U.U.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.", -"U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.K.U.K.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.U.U.K.U.U.U.K.U.U.U.U.K.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.K.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.K.U.K.U.U.U.U.K.U.K.U.U.U.U.U.U.K.U.U.U.K.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.K.U.K.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.K.U.U.U.U.U.U.K.U.U.K.U.U.U.K.U.K.U.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.", -"U.K.U.K.K.U.K.U.U.K.K.U.K.U.U.K.K.U.U.K.K.U.U.K.U.K.U.K.K.U.K.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.K.U.K.U.U.K.K.U.K.U.U.K.U.K.K.U.U.U.U.U.U.U.K.U.U.K.K.U.U.U.U.K.U.U.U.U.K.U.U.U.U.K.K.U.U.U.U.K.K.U.K.U.K.U.K.U.U.K.U.U.U.K.U.K.U.U.U.K.U.K.K.U.U.U.U.K.K.U.U.U.K.U.K.U.U.K.K.U.K.U.U.K.U.K.K.U.U.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.U.K.K.U.K.U.U.U.K.U.K.U.U.K.K.U.U.K.U.K.K.U.U.K.K.U.K.U.U.K.K.U.U.K.U.K.K.U.K.U.U.K.K.U.K.U.U.K.U.K.K.U.U.K.U.U.K.U.U.U.U.U.U.U.U.K.K.U.K.U.U.K.U.K.K.U.K.U.U.K.U.K.K.U.U.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.K.U.U.U.U.K.U.U.U.K.K.U.U.U.U.K.K.U.U.K.U.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.K.K.U.K.U.U.K.U.K.K.U.U.K.U.K.K.U.K.U.U.K.K.U.K.U.U.K.U.K.K.U.U.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.U.U.K.U.K.U.U.K.K.U.K.U.U.K.K.U.U.K.K.U.K.U.U.K.K.U.U.K.U.K.K.U.U.K.U.K.K.U.K.U.U.K.K.U.K.U.U.K.K.U.U.K.K.U.U.K.U.K.U.K.K.U.K.U.U.U.U.U.U.U.U.U.K.U.U.U.U.U.K.U.K.U.K.U.U.K.K.U.K.U.U.K.U.K.K.U.K.U.U.U.U.U.K.U.U.U.K.U.U.U.U.U.U.U.U.U.U.U.K.U.U.K.K.U.U.U.U.K.K.U.K.U.K.U.K.U.U.K.U.U.U.K.U.U.U.U.U.K.U.K.K.U.U.U.U.U.K.U.U.U.", -"K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.U.K.U.U.K.U.K.U.U.U.K.U.U.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.K.K.U.K.U.K.U.K.U.U.K.U.K.U.K.U.K.K.U.K.U.K.K.U.U.U.K.U.K.U.K.U.U.K.U.K.U.K.U.K.K.U.U.K.K.U.U.U.K.U.K.U.U.U.K.U.K.U.K.U.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.K.U.K.U.K.U.K.U.U.K.K.U.U.K.U.K.K.U.U.K.K.U.K.U.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.U.K.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.U.K.U.K.K.U.K.U.U.K.U.K.U.U.U.K.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.K.K.U.K.U.K.K.U.U.K.U.K.K.K.U.K.U.K.K.U.U.U.K.U.K.U.K.U.K.U.K.U.U.K.K.U.U.U.K.U.K.U.K.U.K.U.U.U.K.U.K.U.K.U.K.U.U.K.K.U.U.U.U.K.K.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.K.U.K.U.K.U.K.U.U.K.K.U.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.U.U.U.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.U.U.U.K.U.U.K.U.K.U.U.U.K.U.U.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.U.U.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.K.K.U.K.U.K.U.K.U.U.K.U.K.U.K.U.U.K.U.K.U.K.U.K.K.U.U.K.K.U.U.K.K.U.K.U.U.U.K.U.K.U.K.K.U.K.K.U.", -"U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.K.U.U.K.U.K.K.K.U.K.K.U.K.K.K.U.K.U.K.U.K.U.K.U.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.K.K.U.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.K.U.U.K.U.K.K.U.K.U.K.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.U.K.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.K.U.K.U.K.U.K.K.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.U.K.K.K.K.K.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.K.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.U.K.U.U.K.U.K.K.K.U.K.K.U.K.K.K.U.K.U.K.U.K.U.K.U.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.U.K.K.K.U.K.K.K.U.U.K.U.K.K.U.K.U.K.U.K.U.K.U.K.K.", -"K.U.K.U.K.U.K.U.U.K.K.U.K.U.K.U.U.K.U.U.U.U.U.K.K.U.U.K.U.K.K.U.U.K.U.K.U.K.U.K.K.U.U.K.U.U.K.K.U.K.U.U.K.U.K.K.K.U.K.U.K.K.K.U.K.U.U.K.U.U.K.U.U.K.K.K.U.K.K.U.K.U.U.K.U.U.K.U.U.K.K.U.U.K.K.U.U.U.K.K.K.U.K.K.U.U.K.U.U.K.K.K.K.K.K.U.K.K.U.K.K.U.K.U.U.U.K.U.U.K.U.U.K.U.U.K.K.U.K.U.K.K.K.U.K.K.U.K.U.K.U.U.K.K.U.K.K.K.K.U.K.U.U.K.U.U.K.U.U.K.U.U.K.U.K.U.U.K.K.U.K.U.K.U.U.K.U.U.K.U.U.K.K.U.K.U.K.U.K.U.U.K.K.U.K.K.U.K.U.K.K.K.K.U.K.U.U.K.U.K.U.K.U.K.K.U.K.U.K.U.K.U.U.K.K.U.K.K.U.K.U.K.K.K.U.K.K.U.U.K.U.K.U.K.U.K.K.U.U.K.U.U.K.U.U.K.K.U.U.K.K.U.K.U.K.U.U.U.K.U.U.K.U.U.U.K.K.U.K.K.K.U.U.K.U.U.K.K.U.K.U.K.U.U.K.U.U.K.K.U.K.U.U.K.K.U.K.K.U.K.U.K.U.U.K.U.U.K.K.U.K.U.K.K.K.U.K.K.U.K.U.K.U.U.K.K.U.K.K.K.K.U.U.K.K.U.K.U.K.U.U.K.U.U.K.U.U.K.U.K.K.U.K.K.U.K.U.K.U.U.K.U.U.K.K.U.K.U.K.U.K.U.U.K.K.U.K.U.K.U.U.K.U.U.U.U.U.K.K.U.U.K.U.K.K.U.U.K.U.K.U.K.U.K.K.U.U.K.U.U.K.K.U.K.U.U.K.U.K.K.K.U.K.U.K.K.K.U.K.U.U.K.U.U.K.U.K.U.K.K.U.K.K.U.K.U.U.K.U.U.K.U.U.K.K.K.U.K.K.U.U.U.K.K.K.U.K.K.U.U.K.U.K.U.K.K.K.K.K.U.K.K.U.K.K.U.U.K.U.U.K.U.", -"K.K.U.K.K.K.U.K.K.U.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.U.U.K.U.K.K.K.U.K.K.U.K.K.K.U.K.K.K.U.K.K.K.K.K.K.K.K.K.K.U.K.K.U.U.K.K.K.K.U.K.K.K.K.K.U.U.K.K.U.K.K.U.K.K.U.K.K.K.K.K.U.U.K.K.K.U.K.K.K.K.U.U.K.K.U.K.K.K.K.K.U.U.K.K.U.U.K.K.U.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.U.K.K.U.U.K.K.U.U.K.K.K.K.K.U.K.U.K.K.L.K.K.U.K.K.U.K.K.U.K.K.U.K.K.K.K.U.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.U.K.K.U.K.K.U.K.K.K.U.K.K.K.U.U.K.U.K.U.K.U.K.U.K.U.K.K.K.K.K.K.U.K.K.K.U.K.U.K.K.K.U.U.K.K.U.U.K.K.U.K.K.U.K.K.K.U.K.K.U.U.K.K.U.K.K.K.K.K.U.U.K.K.K.U.K.U.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.K.U.K.K.K.U.K.K.K.U.U.K.K.K.K.K.K.K.K.U.K.K.K.U.K.K.U.K.K.U.U.K.K.K.K.K.K.K.K.U.K.K.U.K.K.U.U.K.K.U.U.K.K.K.K.K.U.K.U.K.K.L.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.U.K.K.K.U.U.K.K.K.K.K.K.K.K.U.K.K.U.K.K.K.U.K.K.U.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.U.U.K.U.K.K.K.U.K.K.U.K.K.K.U.K.K.K.U.K.K.K.K.K.K.K.K.K.K.U.K.K.U.U.K.K.K.K.U.K.K.K.K.K.U.U.K.K.U.K.K.U.K.K.U.K.K.K.K.K.U.U.K.K.U.K.K.K.K.K.U.U.K.K.U.K.K.K.K.K.U.U.K.K.U.U.K.K.U.K.K.U.K.K.K.K.K.K.K.", -"K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.U.K.U.K.K.U.K.K.K.K.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.K.K.U.K.K.K.K.K.L.K.K.U.K.K.K.U.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.U.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.K.U.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.K.K.K.U.K.K.K.K.U.K.U.K.K.K.K.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.K.K.K.U.K.K.K.K.U.K.U.K.K.K.U.K.K.K.K.U.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.U.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.U.K.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.U.K.K.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.U.K.U.K.K.U.K.K.K.K.K.U.K.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.K.K.U.K.K.K.K.K.L.K.K.U.K.K.K.U.K.K.U.K.K.K.U.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.U.K.U.K.K.U.K.K.K.K.U.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.K.K.U.K.K.K.K.", -"K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.", -"K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.L.J.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.U.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.", -"J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.J.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.U.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.", -"K.K.K.K.K.K.K.K.K.K.K.K.J.K.J.K.K.J.K.K.J.K.K.K.K.K.K.K.K.K.J.K.J.K.K.J.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.J.J.K.K.K.J.K.K.K.K.K.K.K.J.K.K.K.J.K.K.K.K.K.J.K.J.K.K.K.K.J.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.J.K.K.K.K.J.K.K.K.K.K.K.J.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.J.K.K.J.K.K.K.K.K.K.J.K.J.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.J.K.J.K.K.J.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.J.K.K.K.K.K.J.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.J.K.K.K.J.J.K.K.K.J.K.J.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.J.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.J.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.J.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.K.J.K.K.J.K.K.J.K.K.K.K.K.K.K.K.K.J.K.J.K.K.J.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.K.K.K.J.J.J.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.K.J.J.K.K.K.J.K.K.K.J.K.K.K.K.K.J.K.K.K.K.K.K.K.K.K.K.K.J.K.K.K.K.K.J.K.K.K.K.K.K.K.K.J.K.J.K.K.K.K.", -"K.J.K.J.K.J.J.K.K.K.J.K.K.K.J.K.K.K.J.K.K.J.K.J.K.J.J.K.K.J.K.K.J.K.K.K.J.K.K.K.K.J.K.J.J.J.K.J.K.J.K.J.J.K.K.K.J.K.K.K.J.K.K.K.J.K.J.K.K.K.J.K.K.K.K.J.J.K.K.K.K.K.J.K.K.K.J.K.J.K.K.J.J.K.K.K.K.J.K.J.J.K.J.K.J.K.K.K.J.K.J.K.K.K.K.J.K.K.K.J.K.K.K.K.J.K.J.K.K.K.J.K.K.J.K.J.K.J.J.K.K.J.J.K.K.K.K.K.K.K.J.K.J.K.K.K.J.K.J.K.J.K.J.K.K.K.J.K.J.K.J.K.J.K.J.K.K.J.K.K.K.K.J.K.J.K.J.K.K.K.J.K.K.J.J.K.K.J.J.K.K.K.J.K.K.J.K.K.J.K.K.K.J.K.J.K.K.K.K.J.K.K.K.J.K.J.J.K.K.J.J.K.K.K.J.K.K.K.J.K.K.K.J.K.K.K.K.J.K.J.J.K.K.J.J.K.J.K.J.K.K.K.J.K.K.K.K.J.J.K.K.K.J.K.J.K.K.K.J.K.J.K.J.K.J.K.K.K.K.K.K.K.K.J.K.K.K.K.J.K.K.J.K.J.K.J.J.K.K.J.K.K.K.K.J.K.K.J.K.K.K.K.J.K.K.J.K.J.K.J.J.K.K.J.J.K.K.K.K.K.K.K.J.K.J.K.K.K.J.K.J.K.K.J.K.K.K.J.K.K.J.K.J.K.K.K.J.K.K.J.K.K.K.J.K.K.J.K.J.K.K.K.J.K.K.J.K.J.K.J.J.K.K.K.J.K.K.K.J.K.K.K.J.K.K.J.K.J.K.J.J.K.K.J.K.K.J.K.K.K.J.K.K.K.K.J.K.J.J.J.K.J.K.J.K.J.J.K.K.K.J.K.K.K.J.K.K.K.J.K.J.K.J.K.K.K.K.K.K.J.J.K.K.K.K.K.J.K.K.K.J.K.K.K.K.J.J.K.K.K.K.J.K.J.J.K.K.J.J.K.K.K.K.K.J.K.J.K.K.J.K.K.K.J.K.K.K.K.J.K.J.K.", -"K.J.K.K.K.J.K.K.J.K.K.J.K.K.J.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.J.K.K.K.J.K.J.K.K.J.K.J.K.K.K.K.J.K.K.J.K.K.J.K.K.J.K.K.J.K.K.J.K.J.K.J.K.K.J.K.K.J.J.K.K.J.K.J.J.K.K.J.J.K.J.K.K.J.K.J.J.K.K.J.J.K.K.J.K.J.K.J.K.J.K.K.J.J.J.K.K.J.J.K.J.K.J.J.K.K.K.J.K.J.K.J.K.K.J.K.J.J.K.K.J.K.J.K.K.J.J.K.J.K.J.K.J.K.J.J.K.J.K.J.K.K.J.K.K.J.K.J.J.K.J.K.K.J.K.J.K.K.J.K.J.K.J.K.J.K.J.K.K.J.K.J.J.K.J.K.K.J.K.J.K.K.K.K.J.K.J.K.J.K.K.K.J.K.J.K.J.K.J.K.K.J.J.K.J.K.K.J.K.K.J.J.K.K.J.K.J.K.J.K.J.K.K.J.K.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.J.K.K.J.J.K.J.K.K.J.J.K.K.J.K.K.J.K.K.J.J.K.J.K.K.J.K.J.K.J.K.K.J.K.J.K.J.K.J.K.J.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.J.K.J.K.J.K.J.K.J.K.J.K.J.J.K.K.J.K.J.K.K.J.J.K.J.K.J.K.J.K.J.J.K.J.K.J.K.K.J.K.K.J.J.K.J.K.J.K.K.J.K.J.J.K.J.K.K.J.J.K.J.K.K.J.K.J.K.J.K.K.J.K.K.J.K.J.K.K.K.J.K.K.J.K.K.J.K.K.J.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.J.K.K.K.J.K.J.K.K.J.K.J.K.K.K.K.J.K.K.J.K.K.J.K.K.J.K.K.J.K.K.J.K.J.K.J.K.K.J.K.J.K.J.K.K.J.K.J.J.K.K.J.K.K.J.K.J.K.K.J.K.K.J.K.J.K.K.J.K.J.K.J.K.J.K.K.J.K.J.K.K.J.K.K.J.K.K.J.K.K.K.J.K.J.K.J.K.K.", -"J.K.K.J.J.K.K.J.K.J.K.K.J.K.K.J.K.J.J.K.J.K.K.J.K.K.J.K.K.K.K.J.J.K.J.K.K.J.J.K.J.K.J.J.K.J.J.K.J.K.J.K.K.K.J.K.J.K.K.J.K.J.J.K.J.K.J.K.K.J.K.J.J.K.J.K.K.K.K.K.J.K.K.K.K.J.K.J.J.K.K.K.J.K.K.J.K.K.J.K.J.K.K.K.J.K.K.J.K.J.K.K.K.J.K.J.J.K.J.K.K.K.J.K.J.K.K.J.K.J.K.K.J.J.K.J.K.J.K.K.K.K.K.J.K.J.K.K.K.K.K.K.J.K.K.J.K.J.K.K.K.K.K.K.K.J.J.K.J.K.J.K.K.J.K.J.K.J.K.J.J.K.J.K.J.K.K.K.K.J.K.J.J.K.K.J.J.K.K.J.K.J.K.K.J.K.K.J.K.K.K.J.K.J.K.K.K.J.K.J.J.K.K.J.K.K.K.J.K.K.K.J.K.J.K.K.J.K.K.J.K.J.J.K.J.K.K.J.K.K.J.K.K.K.K.J.J.K.K.K.K.J.K.J.J.K.J.K.K.J.K.K.J.K.K.K.K.J.K.J.J.K.K.J.K.J.K.J.K.J.K.K.K.J.K.J.K.J.J.K.J.K.K.J.K.K.J.K.K.J.K.J.K.J.K.K.K.J.J.K.K.J.K.K.J.J.K.J.K.J.K.K.K.K.K.J.K.J.K.K.K.K.K.K.J.K.K.J.K.J.K.K.K.J.K.J.J.K.J.K.J.K.K.K.K.J.K.J.K.J.K.J.J.K.J.K.K.K.J.K.K.J.J.K.J.K.K.J.J.K.K.J.K.J.K.K.J.K.K.J.K.J.J.K.J.K.K.J.K.K.J.K.K.K.K.J.J.K.J.K.K.J.J.K.J.K.J.J.K.J.J.K.J.K.J.K.K.K.J.K.J.K.K.J.K.J.J.K.J.K.J.K.K.J.J.J.K.J.J.K.K.K.K.K.J.K.J.K.K.J.K.J.J.K.J.K.K.J.K.K.J.K.J.K.J.K.K.K.J.J.K.J.K.J.K.K.J.K.K.J.J.K.J.K.K.K.J.K.J.K.K.J.", -"K.J.J.K.K.J.J.K.J.K.K.J.J.K.J.K.J.K.K.J.K.J.K.K.J.K.K.J.K.J.K.J.J.K.K.J.J.K.K.J.K.J.J.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.K.J.J.K.J.K.K.K.J.J.J.J.K.J.J.J.K.K.J.K.J.J.K.K.J.J.J.J.K.K.K.K.J.J.K.K.J.K.J.J.J.K.J.K.J.J.K.J.J.K.J.K.K.J.J.K.J.K.K.J.J.K.J.J.K.J.J.K.J.J.J.K.K.J.J.K.J.K.K.J.J.K.K.J.K.J.J.K.K.J.K.J.J.K.K.J.J.K.J.K.K.J.J.K.J.J.J.J.K.K.K.K.J.J.J.J.K.K.J.K.J.K.J.J.K.K.K.K.J.J.J.J.K.K.K.J.J.K.K.J.J.K.J.K.K.J.J.K.J.K.K.J.J.K.J.K.K.J.K.J.J.K.K.J.J.K.K.J.J.K.K.J.K.J.J.K.K.J.K.J.J.K.J.K.K.J.K.J.J.K.K.J.K.J.K.J.K.J.K.K.J.J.J.J.K.J.J.K.J.K.J.K.J.J.K.K.J.J.J.J.K.K.K.K.J.K.J.J.K.K.J.K.K.J.K.J.J.K.J.K.K.J.K.J.J.K.K.J.K.J.K.J.K.J.J.K.K.J.K.J.J.K.J.K.K.J.J.K.J.K.K.J.J.K.K.J.K.J.J.K.K.J.K.J.J.K.K.J.J.K.J.K.K.J.J.J.K.K.J.K.J.J.K.K.J.J.J.J.K.K.J.J.K.K.K.K.J.J.J.K.J.J.J.J.K.K.K.J.J.K.K.J.J.K.J.K.K.J.J.K.J.K.J.K.K.J.K.J.K.K.J.K.K.J.K.J.K.J.J.K.K.J.J.K.K.J.K.J.J.K.J.K.K.J.K.J.J.K.J.J.K.J.J.K.K.J.J.K.J.K.K.K.J.J.J.J.K.K.J.J.K.K.J.K.J.J.K.K.J.J.J.J.K.K.K.K.J.J.K.K.J.J.K.K.J.K.J.K.J.J.K.J.J.K.J.K.K.J.J.K.J.K.J.J.J.K.J.J.K.J.J.K.J.J.", -"J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.K.J.J.J.K.J.J.K.J.J.K.J.J.J.J.K.J.J.J.K.K.J.J.J.K.J.K.J.J.J.K.J.J.K.J.J.J.K.J.K.J.J.J.K.K.J.J.J.J.J.J.K.J.K.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.K.J.J.J.J.J.K.J.J.K.J.J.K.J.K.J.J.J.K.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.J.K.J.K.J.J.J.K.K.J.J.K.J.J.K.J.J.K.J.J.J.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.K.J.J.K.J.K.J.J.J.J.J.J.K.J.K.J.J.J.J.K.J.K.J.J.J.J.J.J.K.J.K.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.J.J.K.J.J.J.K.J.J.K.J.J.J.K.J.J.J.K.J.J.J.J.J.K.J.J.J.J.J.K.J.J.K.J.J.J.K.J.K.J.J.K.K.J.J.J.J.K.J.J.J.K.J.K.J.J.K.J.J.J.J.J.K.J.J.J.K.J.J.K.J.J.J.J.K.J.J.K.J.J.K.J.J.J.J.K.J.J.K.J.J.J.K.J.K.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.K.J.J.K.J.J.K.J.J.K.J.J.J.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.K.J.K.J.J.K.J.J.J.J.J.J.K.J.K.J.J.J.K.J.J.J.J.J.K.J.J.K.K.K.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.K.J.J.J.K.J.J.K.J.J.K.J.J.J.J.K.J.J.J.K.K.J.J.J.K.J.K.J.J.J.K.J.J.K.J.J.J.K.J.K.J.J.J.K.K.J.J.J.J.J.J.K.J.K.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.K.J.J.J.J.J.K.J.J.K.J.K.J.J.K.J.J.K.J.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.J.K.J.K.J.J.J.K.", -"J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.K.J.J.J.K.J.J.J.J.J.J.J.J.J.J.K.K.J.J.J.J.J.J.J.J.J.J.J.J.K.K.J.J.K.J.K.J.L.H.H.J.J.J.J.K.J.J.J.J.J.J.K.J.J.J.J.J.J.J.H.H.J.J.K.J.J.J.J.J.J.J.K.J.J.K.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.H.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.J.K.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.J.J.J.H.H.J.J.K.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.K.K.J.J.J.K.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.J.J.J.K.J.J.K.H.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.K.J.J.J.K.J.J.J.K.J.J.J.J.J.J.J.J.J.J.K.K.J.J.J.J.J.J.J.J.J.J.J.J.K.K.J.J.K.J.K.J.L.H.H.J.J.J.J.K.J.J.J.J.J.J.K.J.J.J.J.J.J.J.H.H.J.J.K.J.J.J.J.J.J.J.K.J.J.K.J.J.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.K.J.K.J.J.K.J.J.J.J.K.J.J.", -"J.J.J.K.K.J.K.J.J.J.J.J.K.K.J.J.J.K.J.J.J.J.J.J.J.J.J.K.J.K.K.J.J.J.J.J.J.J.J.K.J.K.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.K.J.K.K.J.J.J.J.K.J.K.K.J.J.L.K.J.J.J.J.K.J.K.K.J.J.J.J.J.J.K.J.J.J.J.J.K.K.J.J.J.K.J.J.K.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.K.J.J.H.L.J.J.J.J.K.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.J.J.J.K.K.J.J.K.J.J.J.J.J.K.K.J.J.J.J.J.J.H.J.J.J.J.K.J.J.J.J.K.J.K.K.J.J.J.J.J.J.K.K.J.J.K.K.J.J.K.J.J.J.J.K.J.J.J.J.K.J.J.J.J.J.K.J.J.J.K.K.J.J.K.L.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.J.K.J.J.J.K.J.J.J.K.J.K.J.K.K.J.J.J.J.K.J.K.K.J.J.L.K.J.J.J.J.K.J.K.K.J.J.J.J.J.J.K.J.K.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.K.J.J.J.J.J.J.K.J.J.J.J.J.J.H.L.J.J.J.J.K.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.J.J.J.K.K.J.J.K.J.J.J.J.J.K.K.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.J.K.J.K.K.J.J.J.J.J.J.K.J.J.J.K.K.J.K.J.J.J.J.J.K.K.J.J.J.K.J.J.J.J.J.J.J.J.J.K.J.K.K.J.J.J.J.J.J.J.J.K.J.K.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.J.J.K.J.K.K.J.J.J.J.K.J.K.K.J.J.L.K.J.J.J.J.K.J.K.K.J.J.J.J.J.J.K.J.J.J.J.J.K.K.J.J.J.K.J.K.J.J.J.J.J.K.J.J.J.J.J.J.J.K.J.J.J.J.J.", -"J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.H.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.K.J.J.J.J.J.J.H.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.K.J.K.J.J.J.J.J.J.J.J.J.J.J.L.J.J.J.J.H.K.J.J.J.J.J.J.H.K.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.L.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.K.J.J.J.J.J.J.H.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.K.J.K.J.J.J.J.J.J.J.J.J.J.L.H.J.J.J.J.H.K.J.J.J.J.J.J.H.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.H.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.J.K.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.K.J.J.J.J.J.J.H.K.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.", -"J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.L.H.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.L.H.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.", -"J.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.J.H.J.H.J.J.H.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.H.J.J.H.J.J.H.J.J.J.J.H.H.J.J.J.J.J.J.H.J.H.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.H.J.J.H.J.H.H.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.H.J.J.H.H.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.H.J.J.H.J.J.H.J.J.J.J.H.H.J.J.J.J.J.J.H.J.H.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.J.H.J.H.J.J.H.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.", -"J.H.J.J.H.J.J.J.J.H.J.H.J.J.J.H.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.H.J.J.H.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.H.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.J.H.J.J.J.J.J.H.J.H.J.H.J.J.J.H.J.J.H.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.H.J.J.H.J.J.J.J.H.J.J.H.J.J.J.J.H.J.J.H.J.J.H.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.H.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.J.J.J.H.J.H.J.J.J.J.J.H.J.H.J.H.J.J.H.J.J.J.J.H.J.H.J.J.J.H.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.H.J.J.H.J.J.J.J.J.H.J.J.H.J.J.J.J.J.H.J.H.J.J.H.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.H.J.J.H.J.J.H.J.J.J.J.J.J.J.", -"H.J.H.J.J.H.H.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.J.H.J.J.H.J.J.H.H.J.H.J.J.H.H.J.H.J.J.J.H.H.J.H.J.J.J.H.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.H.H.J.J.H.J.J.J.H.J.H.H.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.H.J.H.J.H.J.J.H.H.J.J.H.H.J.J.H.J.H.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.H.J.H.J.J.H.J.J.H.J.H.J.J.J.J.H.J.H.H.J.J.H.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.H.J.J.H.J.H.H.J.J.H.H.J.J.J.J.J.J.H.H.J.J.J.H.J.H.J.J.H.H.J.H.J.J.J.J.J.J.J.J.J.J.H.J.J.H.J.J.H.H.J.H.J.J.H.H.J.J.H.J.H.H.J.J.H.J.J.H.J.H.J.J.J.J.H.J.H.H.J.H.J.J.J.J.J.J.H.J.J.J.J.J.H.H.J.J.H.J.J.J.H.J.H.H.J.J.J.H.J.J.J.J.J.J.H.H.J.J.J.H.J.J.H.J.J.H.J.J.H.J.J.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.H.J.H.H.J.J.H.J.H.H.J.H.J.J.H.J.J.H.J.H.J.J.J.J.H.J.H.H.J.J.H.J.J.J.J.J.J.J.J.H.J.J.H.J.J.J.J.H.J.J.H.J.H.H.J.J.H.H.J.J.J.J.J.J.H.H.J.J.J.H.J.H.J.H.J.J.H.H.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.J.H.J.J.H.J.J.H.H.J.H.J.J.H.H.J.H.J.J.J.H.H.J.H.J.J.J.H.J.J.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.H.H.J.J.H.J.J.J.H.J.H.H.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.H.J.H.J.H.J.J.J.H.J.J.H.H.J.J.H.J.H.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.", -"H.J.J.H.J.J.J.H.H.J.H.J.H.J.J.H.J.H.H.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.J.J.H.J.J.H.J.J.J.H.J.H.J.H.J.H.J.H.J.H.J.H.J.H.H.J.H.H.J.H.J.H.J.J.J.H.J.H.J.H.J.J.H.J.J.H.H.J.H.H.J.H.J.H.J.J.H.J.H.J.J.J.H.J.J.H.J.J.H.J.H.J.J.H.J.J.H.J.H.H.J.H.J.J.H.J.H.H.J.H.H.J.H.J.H.J.J.H.J.J.H.H.J.J.H.J.H.H.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.H.J.J.J.H.J.H.J.H.H.J.J.H.J.J.H.J.J.H.J.J.H.H.J.H.J.H.J.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.H.J.H.J.J.H.J.H.H.J.J.H.J.H.J.J.J.H.J.H.J.J.H.J.J.J.H.J.J.H.J.H.H.J.H.J.J.H.J.J.H.J.H.J.H.J.H.J.H.J.H.J.H.J.J.J.H.J.H.J.H.J.J.H.J.J.H.H.J.H.H.J.H.J.H.J.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.H.J.H.J.J.H.J.H.H.J.H.J.J.H.J.J.H.J.J.H.J.J.H.J.J.H.H.J.J.H.J.H.H.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.H.J.J.J.H.J.H.J.H.H.J.J.H.J.J.H.J.J.H.J.J.H.H.J.H.J.H.J.J.H.J.H.J.J.H.J.J.H.J.J.J.H.H.J.H.J.H.J.J.H.J.H.H.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.J.J.H.J.J.H.J.J.J.H.J.H.J.H.J.H.J.H.J.H.J.H.J.H.H.J.H.H.J.H.J.H.J.J.J.H.J.H.J.H.J.J.H.J.J.H.H.J.H.H.J.H.J.H.J.J.H.J.H.J.J.J.H.J.J.H.H.J.H.J.H.J.J.H.J.J.H.J.H.H.J.H.J.J.H.J.H.H.J.H.H.J.H.", -"H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.J.H.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.J.H.J.H.H.J.H.J.H.J.J.H.J.H.H.H.H.J.H.J.J.H.H.J.H.J.J.H.H.J.H.J.H.H.J.J.J.H.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.J.J.H.J.H.H.J.J.H.J.H.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.J.J.H.H.J.J.H.J.H.J.H.J.H.H.J.H.J.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.J.H.J.H.J.H.H.J.H.J.H.J.H.J.J.H.J.H.J.J.H.J.H.H.J.H.H.H.H.J.H.J.H.J.J.H.J.H.H.J.H.J.H.H.J.H.J.J.J.H.J.H.J.H.J.H.H.J.H.J.H.J.J.H.J.H.H.J.H.J.H.H.J.H.J.H.J.J.H.J.H.H.H.H.J.H.J.H.H.H.J.H.J.J.H.J.H.J.H.J.H.J.J.H.H.J.H.H.H.J.H.H.J.J.H.J.H.H.J.J.H.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.J.J.H.H.J.J.H.J.H.J.H.J.H.H.J.H.J.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.J.H.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.J.H.J.H.H.J.H.J.H.J.J.H.J.H.H.H.H.J.H.J.J.H.H.J.H.J.J.H.H.J.H.H.H.J.J.H.J.J.H.J.H.J.H.J.J.H.H.J.H.J.J.H.H.H.J.H.J.J.H.H.", -"J.H.J.H.J.H.H.J.H.J.J.H.H.J.J.H.H.H.J.H.J.J.H.J.J.H.J.H.H.J.H.J.H.H.H.H.J.H.H.J.H.J.H.J.J.H.J.H.H.J.J.H.H.J.J.H.J.H.H.J.J.H.H.J.J.H.J.H.H.J.J.J.H.J.J.H.H.H.H.J.H.J.H.J.J.H.H.H.H.H.J.H.J.H.H.J.J.H.H.H.J.H.J.H.H.J.J.H.H.J.J.H.H.H.J.H.J.H.H.J.H.H.H.J.H.J.J.H.H.J.H.J.J.H.J.H.J.H.J.J.J.H.J.H.H.J.J.H.H.J.J.H.H.J.H.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.H.J.J.H.H.H.H.J.J.H.J.H.H.J.J.H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.H.J.H.J.H.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.H.J.H.J.H.H.J.H.H.H.J.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.J.H.H.J.H.J.H.J.J.H.H.H.H.J.H.J.H.J.J.H.H.H.H.J.J.H.J.H.H.J.H.J.J.H.H.J.H.J.J.H.H.J.J.H.H.J.J.H.H.J.H.H.J.H.J.H.J.H.J.H.H.J.H.J.H.J.J.H.J.H.J.H.J.J.J.H.J.H.H.J.J.H.H.J.J.H.H.J.H.J.H.J.H.J.J.H.J.J.H.J.J.H.J.H.J.H.H.J.H.J.H.J.H.J.J.H.H.H.H.J.J.H.J.H.H.J.J.H.J.H.J.H.H.J.H.J.J.H.H.J.J.H.H.H.J.H.J.J.H.J.J.H.J.H.H.J.H.J.H.H.H.H.J.H.H.J.H.J.H.J.J.H.J.H.H.J.J.H.H.J.J.H.J.H.H.J.J.H.H.J.J.H.J.H.H.J.J.J.H.J.J.H.H.H.H.J.H.J.H.J.J.H.H.H.H.H.J.H.J.H.H.J.J.H.H.J.J.H.H.J.H.H.J.H.H.J.J.H.H.H.J.H.J.H.H.J.H.J.H.J.H.H.J.H.", -"J.H.J.H.H.J.H.H.J.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.J.H.J.H.J.H.H.H.J.H.J.J.J.H.H.J.H.H.H.J.H.J.H.H.H.H.H.H.J.J.H.J.H.H.H.H.H.J.H.H.J.J.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.J.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.J.H.H.H.H.H.H.J.H.H.H.H.J.H.J.H.H.H.H.H.J.H.H.J.H.H.H.J.H.H.H.H.J.J.H.H.H.H.H.H.J.J.H.J.H.H.H.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.H.H.H.H.H.H.H.J.H.H.J.H.H.H.J.H.J.J.H.H.J.H.H.H.H.H.J.H.J.H.J.H.H.J.H.H.H.H.H.H.H.J.H.H.H.J.H.J.H.H.H.H.H.H.J.H.J.H.J.J.H.J.H.H.H.J.H.J.H.H.H.H.H.H.J.J.H.J.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.J.H.J.H.J.H.H.H.H.J.H.H.J.H.J.H.J.H.J.H.J.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.J.H.H.H.H.H.H.J.H.H.H.H.J.H.J.H.H.H.H.H.J.H.H.J.H.H.H.J.H.H.H.H.J.J.H.H.H.H.H.H.J.J.H.J.H.H.H.H.H.J.H.J.H.J.H.H.J.H.H.J.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.J.H.J.H.J.H.H.H.J.H.J.J.J.H.H.J.H.H.H.J.H.J.H.H.H.H.H.H.J.J.H.J.H.H.H.H.H.J.H.H.J.J.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.J.H.H.J.H.J.H.J.H.H.H.H.H.", -"H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.J.H.H.H.H.J.G.L.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.J.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.J.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.J.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.J.H.H.H.H.J.G.L.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.J.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.J.J.H.", -"H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.", -"H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.J.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.", -"H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.", -"H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.H.G.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.G.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.H.G.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.H.G.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.G.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.G.H.H.H.G.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.G.H.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.", -"G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.G.H.H.H.H.H.H.G.H.H.G.H.H.H.G.H.H.G.G.H.H.H.H.H.H.G.H.H.G.H.H.H.H.G.H.G.H.H.H.H.H.H.H.H.H.H.G.G.H.H.H.H.H.G.H.H.G.H.H.H.H.G.H.G.H.H.H.H.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.G.H.H.H.H.H.H.G.H.H.H.G.H.H.H.G.G.H.H.H.H.G.H.H.G.H.H.H.G.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.G.H.G.H.H.H.H.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.G.H.H.H.H.H.G.H.H.G.H.H.H.G.G.H.H.H.H.G.H.H.G.G.H.H.G.H.H.H.H.H.G.H.G.H.H.H.H.H.H.H.H.H.H.G.H.H.H.G.H.H.G.G.H.H.H.H.H.H.G.H.G.H.H.H.H.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.G.H.G.H.H.H.G.H.H.G.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.G.H.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.G.H.G.H.H.H.H.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.H.G.H.H.H.H.H.H.G.H.H.G.H.H.H.G.H.H.G.G.H.H.H.H.H.H.G.H.H.G.H.H.H.H.G.H.G.H.H.H.H.H.H.H.H.H.H.G.G.H.H.H.H.H.G.H.H.G.H.H.H.H.G.H.G.H.H.H.H.G.H.H.G.H.H.H.H.G.H.H.G.H.H.H.H.H.H.H.H.H.H.H.H.H.H.G.G.G.H.H.H.H.H.G.H.H.G.H.H.H.H.G.", -"H.H.G.G.G.H.G.G.H.G.H.G.G.G.H.H.G.H.H.G.G.H.G.H.G.H.H.G.H.G.G.H.G.H.H.H.H.G.G.H.G.H.G.H.H.G.H.G.G.G.H.H.H.H.G.H.G.H.G.G.G.G.H.H.H.G.H.G.G.H.H.H.H.H.G.H.G.H.G.H.H.H.G.H.G.H.H.G.H.G.H.G.H.G.H.G.H.H.G.G.G.H.G.G.G.H.G.G.G.G.H.H.H.G.H.G.G.H.G.H.G.G.H.G.G.H.H.H.H.H.G.H.G.H.G.H.H.G.H.G.H.H.G.H.Z.H.G.G.G.H.G.G.G.H.G.G.G.G.H.H.H.G.H.H.H.G.H.G.H.G.G.H.G.H.H.G.H.H.G.H.G.H.H.G.H.G.H.G.H.G.H.G.H.H.G.G.G.H.G.G.H.G.H.G.G.G.H.H.G.H.H.G.G.H.G.H.G.H.H.G.H.G.H.H.H.H.G.H.G.H.H.G.H.G.H.G.H.H.G.H.G.G.H.H.H.H.G.H.G.H.G.G.G.G.H.H.H.G.H.H.G.H.H.H.H.H.G.H.G.H.H.G.H.H.G.H.G.H.H.G.H.G.H.G.H.G.H.G.H.H.G.G.G.H.G.G.G.H.G.G.G.G.H.H.G.H.G.H.H.G.H.G.H.H.G.H.H.H.G.G.H.H.G.H.G.H.G.H.H.G.H.G.H.H.G.H.Z.H.G.G.G.H.G.G.G.H.G.G.G.G.H.H.H.G.H.H.H.G.H.G.H.G.G.H.G.H.H.G.H.H.G.H.G.H.H.G.H.G.H.G.H.G.H.G.H.H.G.G.G.H.G.G.H.G.H.G.G.G.H.H.G.H.H.G.G.H.G.H.G.H.H.G.H.G.G.H.G.H.H.H.H.G.G.H.G.H.G.H.H.G.H.G.G.G.H.H.H.H.G.H.G.H.G.G.G.G.H.H.H.G.H.G.G.H.H.H.H.H.G.H.G.H.G.H.H.H.G.H.G.H.H.G.H.G.H.G.H.G.H.G.H.H.G.G.G.H.G.G.G.H.G.G.G.G.H.H.H.H.H.G.G.H.G.H.H.G.H.H.G.H.G.H.", -"H.H.H.H.H.G.G.H.G.H.H.H.H.H.G.H.H.G.H.G.H.G.H.H.H.G.H.H.G.H.H.H.G.H.G.G.G.H.H.G.G.H.H.G.H.H.H.G.H.H.H.G.G.H.G.G.H.G.G.H.H.H.G.H.H.H.G.H.G.H.G.H.G.H.H.H.H.G.H.G.H.G.H.G.H.H.G.H.H.H.G.H.H.H.G.G.H.H.H.H.H.G.G.H.H.G.H.H.H.H.G.H.H.H.G.H.G.H.G.H.H.G.H.H.G.H.G.H.H.G.H.H.H.H.G.H.H.H.G.H.H.G.H.G.G.G.H.H.H.G.G.H.H.G.G.H.H.H.H.G.G.H.G.H.H.H.G.H.G.H.H.H.H.G.H.G.H.G.H.G.H.H.G.H.H.H.G.H.H.H.G.G.H.H.H.H.H.G.G.H.G.H.H.H.H.H.G.H.H.G.H.G.H.G.H.H.H.G.H.H.G.H.G.H.H.G.H.H.H.H.G.H.H.H.G.H.H.G.H.G.H.H.H.G.G.H.G.G.H.G.G.H.G.H.G.H.G.H.G.H.G.H.G.H.G.H.H.H.H.G.H.G.H.G.H.G.H.H.G.H.H.H.G.H.H.H.G.G.H.G.H.H.H.G.G.H.H.G.H.H.H.H.G.H.G.H.H.H.H.H.H.H.G.H.G.H.H.H.H.H.H.G.H.H.H.H.G.H.H.H.G.H.H.G.H.G.G.G.H.H.H.G.G.H.H.G.G.H.H.H.H.G.G.H.G.H.H.H.G.H.G.H.H.H.H.G.H.G.H.G.H.G.H.H.G.H.H.H.G.H.H.H.G.G.H.H.H.H.H.G.G.H.G.H.H.H.H.H.G.H.H.G.H.G.H.G.H.H.H.G.H.H.G.H.H.H.G.H.G.G.G.H.H.G.G.H.H.G.H.H.H.G.H.H.H.G.G.H.G.G.H.G.G.H.H.H.G.H.H.H.G.H.G.H.G.H.G.H.H.H.H.G.H.G.H.G.H.G.H.H.G.H.H.H.G.H.H.H.G.G.H.H.H.H.H.G.G.H.H.G.H.H.H.H.G.H.H.H.G.H.G.H.G.H.H.G.H.G.G.H.H.H.", -"H.G.G.H.G.H.H.H.H.G.G.H.G.G.H.G.G.H.G.H.H.G.G.G.G.H.G.H.H.G.H.G.G.G.G.Z.H.G.G.H.H.H.G.H.G.H.G.H.H.G.H.G.H.G.G.G.G.H.H.G.G.G.H.G.G.G.H.G.H.G.H.H.H.G.G.G.G.H.G.H.G.H.H.H.G.H.H.G.G.G.H.G.G.H.G.G.H.G.G.H.G.H.H.H.G.H.G.H.G.G.H.G.G.G.H.G.H.G.H.H.G.H.G.H.H.H.G.H.G.H.G.G.G.G.H.G.G.G.H.G.G.H.G.G.G.G.G.H.G.H.H.H.G.H.H.G.H.G.H.G.H.G.H.G.G.H.H.H.H.G.G.G.G.H.G.H.G.H.H.H.G.H.H.G.G.G.H.G.G.H.G.G.H.G.G.H.G.H.H.H.H.G.G.H.G.G.H.G.G.H.G.H.H.G.G.G.G.H.G.H.H.G.H.G.G.H.G.G.G.H.H.G.G.G.H.G.G.H.G.G.H.G.H.G.H.G.G.G.G.H.H.G.H.G.H.G.H.G.H.G.H.G.H.H.H.G.G.G.G.H.G.H.G.H.H.H.G.H.H.G.G.G.H.G.G.H.G.G.H.H.G.H.G.H.H.H.G.H.G.H.G.G.H.G.H.H.G.G.G.H.G.H.H.G.H.G.G.G.H.G.G.H.G.G.G.H.G.G.G.G.H.G.G.H.G.G.G.G.G.H.G.H.H.H.G.H.H.G.H.G.H.G.H.G.H.G.G.H.H.H.H.G.G.G.G.H.G.H.G.H.H.H.G.H.H.G.G.G.H.G.G.H.G.G.H.G.G.H.G.H.H.H.H.G.G.H.G.G.H.G.G.H.G.H.H.G.G.G.G.H.G.H.H.G.H.G.G.G.G.Z.H.G.G.H.H.H.G.H.G.H.G.H.H.G.H.G.H.G.G.G.G.H.H.G.G.G.H.G.G.G.H.G.H.G.H.H.H.G.G.G.G.H.G.H.G.H.H.H.G.H.H.G.G.G.H.G.G.H.G.G.H.G.G.H.G.H.H.H.G.H.G.H.G.G.H.G.G.G.H.G.H.G.H.H.G.H.G.H.H.H.G.G.", -"G.H.G.G.H.G.H.G.G.G.H.G.H.G.H.H.H.G.G.G.H.G.G.H.G.H.H.G.G.H.G.H.G.H.G.G.H.G.G.G.G.G.G.H.G.G.H.G.G.H.G.H.H.G.Z.G.H.G.H.G.H.G.H.H.G.H.H.G.G.H.G.G.H.G.G.G.H.H.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.G.G.H.H.G.H.G.G.G.H.G.H.G.H.H.G.H.H.G.H.G.G.G.H.G.H.G.G.G.G.H.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.G.G.H.H.G.H.G.H.G.H.G.G.G.H.H.G.G.H.G.G.H.G.G.H.G.G.H.H.H.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.H.G.G.H.G.H.G.G.G.H.G.H.G.H.H.H.G.G.G.H.G.G.H.G.H.G.H.G.G.G.H.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.H.G.H.H.G.Z.G.H.G.H.G.H.G.H.H.G.H.H.G.G.H.G.G.H.G.G.H.H.H.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.G.G.H.H.G.H.G.G.G.H.G.H.G.H.H.G.G.G.H.G.H.G.G.G.H.G.H.G.G.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.G.G.H.H.G.H.G.H.G.H.G.G.G.H.H.G.G.H.G.G.H.G.G.H.G.G.H.H.H.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.H.G.G.H.G.H.G.G.G.H.G.H.G.H.H.H.G.G.G.H.G.G.H.G.H.H.G.G.H.G.H.G.H.G.G.H.G.G.G.G.G.G.H.G.G.H.G.G.H.G.H.H.G.Z.G.H.G.H.G.H.G.H.H.G.H.H.G.G.H.G.G.H.G.G.G.H.H.G.G.G.H.G.H.H.G.G.G.G.H.H.G.G.H.G.G.G.G.G.H.H.G.H.G.G.G.H.G.H.G.H.H.G.H.H.G.H.G.G.G.H.H.H.G.G.H.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.H.G.G.G.H.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.H.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.H.G.G.G.G.G.G.G.H.G.H.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.H.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.H.H.G.G.H.G.H.G.H.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.H.G.G.G.G.G.G.G.H.G.H.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.H.G.G.G.H.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.", -"G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.H.G.G.G.G.H.G.G.H.H.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.G.H.G.G.H.G.H.G.G.G.G.G.H.G.H.G.H.H.G.G.G.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.G.G.G.H.H.G.G.G.G.G.G.H.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.H.G.G.H.G.H.G.H.H.H.G.G.G.G.G.G.G.H.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.H.G.H.G.G.H.G.G.H.H.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.G.G.G.G.H.G.H.G.H.H.G.G.G.G.G.G.H.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.G.H.G.G.G.H.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.H.G.G.H.G.H.G.H.H.H.G.G.G.G.G.G.G.H.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.H.G.G.G.G.H.G.G.H.H.G.H.G.G.G.H.G.G.G.G.G.G.G.G.G.G.H.G.G.H.G.H.G.G.G.G.G.H.G.H.G.H.H.G.G.G.G.G.G.H.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.H.G.G.G.G.H.H.G.G.H.G.H.G.H.H.G.G.G.G.G.G.G.G.G.H.G.H.G.G.H.G.H.H.G.G.H.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.H.G.H.G.G.G.H.G.G.H.G.G.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.H.H.G.G.H.G.G.G.H.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.H.G.G.G.H.G.G.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.H.G.G.H.G.H.G.G.H.H.G.G.G.G.G.Z.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.H.G.G.H.G.G.G.H.G.G.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.H.G.G.H.G.G.G.H.G.G.G.G.G.G.Z.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.H.G.G.G.H.G.G.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.H.G.H.G.G.G.H.G.G.H.G.G.H.G.G.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.H.G.G.H.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.", -"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G." -}; diff --git a/sequencer/instruments/Default.inst b/sequencer/instruments/Default.inst deleted file mode 100644 index af358b6..0000000 --- a/sequencer/instruments/Default.inst +++ /dev/null @@ -1,13 +0,0 @@ -"Kick", 36, 100 -"Snare", 38, 100 -"Closed Hat", 42, 80 -"Open Hat", 46, 80 -"Rim Shot", 37, 100 -"Ride", 51, 80 -"Crash", 49, 80 -"Hi Tom", 48, 100 -"Mid Tom", 45, 100 -"Low Tom", 41, 100 -"Hi Conga", 62, 80 -"Low Conga", 63, 80 -"Timbale", 65, 80 diff --git a/sequencer/instruments/GM-Drum.inst b/sequencer/instruments/GM-Drum.inst deleted file mode 100644 index dce977d..0000000 --- a/sequencer/instruments/GM-Drum.inst +++ /dev/null @@ -1,44 +0,0 @@ -"Bass Drum 1", 36, 100 -"Side Stick", 37, 80 -"Acoustic Snare", 38, 100 -"Hand Clap", 39, 80 -"Electric Snare", 40, 100 -"Low Floor Tom", 41, 100 -"Closed Hi-Hat", 42, 80 -"High Floor Tom", 43, 100 -"Pedal Hi-Hat", 44, 80 -"Low Tom", 45, 100 -"Open Hi-Hat", 46, 64 -"Low-Mid Tom", 47, 90 -"Hi-Mid Tom", 48, 90 -"Crash Cymbal 1", 49, 80 -"High Tom", 50, 100 -"Ride Cymbal 1", 51, 75 -"Chinese Cymbal", 52, 75 -"Ride Bell", 53, 75 -"Tambourine", 54, 64 -"Splash Cymbal", 55, 64 -"Cowbell", 56, 64 -"Crash Cymbal 2", 57, 64 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 80 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 80 -"Low Timbale", 66, 80 -"High Agogo", 67, 64 -"Low Agogo", 68, 64 -"Cabasa", 69, 64 -"Maracas", 70, 70 -"Short Whistle", 71, 64 -"Long Whistle", 72, 64 -"Short Guiro", 73, 64 -"Long Guiro", 74, 64 -"Claves", 75, 80 -"Hi Wood Block", 76, 80 -"Low Wood Block", 77, 80 -"Mute Cuica", 78, 64 -"Open Cuica", 79, 64 -"Mute Triangle", 80, 64 -"Open Triangle", 81, 64 diff --git a/sequencer/instruments/GS-Brush.inst b/sequencer/instruments/GS-Brush.inst deleted file mode 100644 index f7195b8..0000000 --- a/sequencer/instruments/GS-Brush.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Bass Drum 1", 36, 100 -"Side Stick", 37, 100 -"Brush Tap", 38, 100 -"Brush Slap", 39, 100 -"Brush Swirl", 40, 100 -"Low Floor Tom", 41, 100 -"Closed Hi-Hat", 42, 100 -"High Floor Tom", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Low Tom", 45, 100 -"Open Hi-Hat", 46, 100 -"Low-Mid Tom", 47, 100 -"Hi-Mid Tom", 48, 100 -"Crash Cymbal 1", 49, 100 -"High Tom", 50, 100 -"Ride Cymbal 1", 51, 100 -"Chinese Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-Electronic.inst b/sequencer/instruments/GS-Electronic.inst deleted file mode 100644 index 2c378ea..0000000 --- a/sequencer/instruments/GS-Electronic.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Elec BD", 36, 100 -"Side Stick", 37, 100 -"Elec SD", 38, 100 -"Hand Clap", 39, 100 -"Gated SD", 40, 100 -"Elec Low Tom 2", 41, 100 -"Closed Hi-Hat", 42, 100 -"Elec Low Tom 1", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Elec Mid Tom 2", 45, 100 -"Open Hi-Hat", 46, 100 -"Elec Mid Tom 1", 47, 100 -"Elec Hi Tom 2", 48, 100 -"Crash Cymbal 1", 49, 100 -"Elec High Tom 1", 50, 100 -"Ride Cymbal 1", 51, 100 -"Reverse Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-Jazz.inst b/sequencer/instruments/GS-Jazz.inst deleted file mode 100644 index 96368f3..0000000 --- a/sequencer/instruments/GS-Jazz.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Bass Drum 1", 36, 100 -"Side Stick", 37, 100 -"Acoustic Snare", 38, 100 -"Hand Clap", 39, 100 -"Electric Snare", 40, 100 -"Low Floor Tom", 41, 100 -"Closed Hi-Hat", 42, 100 -"High Floor Tom", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Low Tom", 45, 100 -"Open Hi-Hat", 46, 100 -"Low-Mid Tom", 47, 100 -"Hi-Mid Tom", 48, 100 -"Crash Cymbal 1", 49, 100 -"High Tom", 50, 100 -"Ride Cymbal 1", 51, 100 -"Chinese Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-Orchestra.inst b/sequencer/instruments/GS-Orchestra.inst deleted file mode 100644 index 9edecea..0000000 --- a/sequencer/instruments/GS-Orchestra.inst +++ /dev/null @@ -1,62 +0,0 @@ -"Closed HH", 27, 100 -"Pedal HH", 28, 100 -"Open HH", 29, 100 -"Hide Cymbal", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Concert BD2", 35, 100 -"Concert BD1", 36, 100 -"Side Stick", 37, 100 -"Concert SD", 38, 100 -"Castanets", 39, 100 -"Concert SD", 40, 100 -"Timpani F", 41, 100 -"Timpani F#", 42, 100 -"Timpani G", 43, 100 -"Timpani G#", 44, 100 -"Timpani A", 45, 100 -"Timpani A#", 46, 100 -"Timpani B", 47, 100 -"Timpani c", 48, 100 -"Timpani c#", 49, 100 -"Timpani d", 50, 100 -"Timpani d#", 51, 100 -"Timpani e", 52, 100 -"Timpani f", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Concert Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Concert Cymbal 1", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 -"Applause", 88, 100 diff --git a/sequencer/instruments/GS-Power.inst b/sequencer/instruments/GS-Power.inst deleted file mode 100644 index 11bf902..0000000 --- a/sequencer/instruments/GS-Power.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"MONDO Kick", 36, 100 -"Side Stick", 37, 100 -"Gated SD", 38, 100 -"Hand Clap", 39, 100 -"Electric Snare", 40, 100 -"Room Low Tom 2", 41, 100 -"Closed Hi-Hat", 42, 100 -"Room Low Tom 1", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Room Mid Tom 2", 45, 100 -"Open Hi-Hat", 46, 100 -"Room Mid Tom 1", 47, 100 -"Room Hi Tom 2", 48, 100 -"Crash Cymbal 1", 49, 100 -"Room High Tom 1", 50, 100 -"Ride Cymbal 1", 51, 100 -"Chinese Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-Room.inst b/sequencer/instruments/GS-Room.inst deleted file mode 100644 index 454fa36..0000000 --- a/sequencer/instruments/GS-Room.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Kick Drum 1", 36, 100 -"Side Stick", 37, 100 -"Acoustic Snare", 38, 100 -"Hand Clap", 39, 100 -"Electric Snare", 40, 100 -"Room Low Tom 2", 41, 100 -"Closed Hi-Hat", 42, 100 -"Room Low Tom 1", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Room Mid Tom 2", 45, 100 -"Open Hi-Hat", 46, 100 -"Room Mid Tom 1", 47, 100 -"Room Hi Tom 2", 48, 100 -"Crash Cymbal 1", 49, 100 -"Room High Tom 1", 50, 100 -"Ride Cymbal 1", 51, 100 -"Chinese Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-SFX.inst b/sequencer/instruments/GS-SFX.inst deleted file mode 100644 index a404b30..0000000 --- a/sequencer/instruments/GS-SFX.inst +++ /dev/null @@ -1,58 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Bass Drum 1", 36, 100 -"Side Stick", 37, 100 -"Acoustic Snare", 38, 100 -"High Q", 39, 100 -"Slap", 40, 100 -"Scratch Push", 41, 100 -"Scratch Pull", 42, 100 -"Sticks", 43, 100 -"Sqare Click", 44, 100 -"Metronome Click", 45, 100 -"Metronome Bell", 46, 100 -"Guitar sld fing.", 47, 100 -"Guitar cutt down", 48, 100 -"Guitar cutt up", 49, 100 -"String slap", 50, 100 -"Fl. Key Click", 51, 100 -"Laughing", 52, 100 -"Screamming", 53, 100 -"Punch", 54, 100 -"Heart Beat", 55, 100 -"Footsteps 1", 56, 100 -"Footsteps 2", 57, 100 -"Aplause", 58, 100 -"Door Creaking", 59, 100 -"Door", 60, 100 -"Scratch", 61, 100 -"Windchime", 62, 100 -"Car-Engine", 63, 100 -"Car-Stop", 64, 100 -"Car-Pass", 65, 100 -"Car-Crash", 66, 100 -"Siren", 67, 100 -"Train", 68, 100 -"Jetplane", 69, 100 -"Helicopter", 70, 100 -"Starship", 71, 100 -"Gun Shot", 72, 100 -"Machine Gun", 73, 100 -"Lasergun", 74, 100 -"Explosion", 75, 100 -"Dog", 76, 100 -"Horse-Gallop", 77, 100 -"Birds", 78, 100 -"Rain", 79, 100 -"Thunder", 80, 100 -"Wind", 81, 100 -"Seashore", 82, 100 -"Stream", 83, 100 -"Bubble", 84, 100 diff --git a/sequencer/instruments/GS-Standard.inst b/sequencer/instruments/GS-Standard.inst deleted file mode 100644 index 96368f3..0000000 --- a/sequencer/instruments/GS-Standard.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"Bass Drum 1", 36, 100 -"Side Stick", 37, 100 -"Acoustic Snare", 38, 100 -"Hand Clap", 39, 100 -"Electric Snare", 40, 100 -"Low Floor Tom", 41, 100 -"Closed Hi-Hat", 42, 100 -"High Floor Tom", 43, 100 -"Pedal Hi-Hat", 44, 100 -"Low Tom", 45, 100 -"Open Hi-Hat", 46, 100 -"Low-Mid Tom", 47, 100 -"Hi-Mid Tom", 48, 100 -"Crash Cymbal 1", 49, 100 -"High Tom", 50, 100 -"Ride Cymbal 1", 51, 100 -"Chinese Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"Mute Hi Conga", 62, 100 -"Open Hi Conga", 63, 100 -"Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/instruments/GS-TR-808.inst b/sequencer/instruments/GS-TR-808.inst deleted file mode 100644 index e47460d..0000000 --- a/sequencer/instruments/GS-TR-808.inst +++ /dev/null @@ -1,61 +0,0 @@ -"High Q", 27, 100 -"Slap", 28, 100 -"Scratch Push", 29, 100 -"Scratch Pull", 30, 100 -"Sticks", 31, 100 -"Square Click", 32, 100 -"Metronome Click", 33, 100 -"Metronome Bell", 34, 100 -"Acoustic Bass Drum", 35, 100 -"808 BD", 36, 100 -"808 Rim Shot", 37, 100 -"808 Snare Drum", 38, 100 -"Hand Clap", 39, 100 -"Gated SD", 40, 100 -"808 Low Tom 2", 41, 100 -"808 CHH", 42, 100 -"808 Low Tom 1", 43, 100 -"808 CHH", 44, 100 -"808 Mid Tom 2", 45, 100 -"808 OHH", 46, 100 -"808 Mid Tom 1", 47, 100 -"808 Hi Tom 2", 48, 100 -"808 Cymbal", 49, 100 -"808 High Tom 1", 50, 100 -"Ride Cymbal 1", 51, 100 -"Reverse Cymbal", 52, 100 -"Ride Bell", 53, 100 -"Tambourine", 54, 100 -"Splash Cymbal", 55, 100 -"Cowbell", 56, 100 -"Crash Cymbal 2", 57, 100 -"Vibraslap", 58, 100 -"Ride Cymbal 2", 59, 100 -"Hi Bongo", 60, 100 -"Low Bongo", 61, 100 -"808 Hi Conga", 62, 100 -"808 Mid Conga", 63, 100 -"808 Low Conga", 64, 100 -"High Timbale", 65, 100 -"Low Timbale", 66, 100 -"High Agogo", 67, 100 -"Low Agogo", 68, 100 -"Cabasa", 69, 100 -"808 Maracas", 70, 100 -"Short Whistle", 71, 100 -"Long Whistle", 72, 100 -"Short Guiro", 73, 100 -"Long Guiro", 74, 100 -"808 Claves", 75, 100 -"Hi Wood Block", 76, 100 -"Low Wood Block", 77, 100 -"Mute Cuica", 78, 100 -"Open Cuica", 79, 100 -"Mute Triangle", 80, 100 -"Open Triangle", 81, 100 -"Shaker", 82, 100 -"Jungle Bell", 83, 100 -"Belltree", 84, 100 -"Castanets", 85, 100 -"Mute Surdo", 86, 100 -"Open Surdo", 87, 100 diff --git a/sequencer/non-sequencer.desktop.in b/sequencer/non-sequencer.desktop.in deleted file mode 100644 index f3a3c8e..0000000 --- a/sequencer/non-sequencer.desktop.in +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Name=Non Sequencer -Comment=Realtime MIDI sequencer for JACK MIDI -Comment[fr]=Séquenceur MIDI temps-réel pour JACK MIDI -Exec=@BIN_PATH@/non-sequencer -Terminal=false -Type=Application -Icon=non-sequencer -Categories=AudioVideo;Audio;Midi; diff --git a/sequencer/src/NSM.C b/sequencer/src/NSM.C deleted file mode 100644 index 8d4c26e..0000000 --- a/sequencer/src/NSM.C +++ /dev/null @@ -1,134 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "NSM.H" - - -#include -#include -#include -#include - -#include "common.h" -#include "config.h" -#include "non.H" -#include "jack.H" -#include "transport.H" - -#include "gui/ui.H" - -#define OSC_INTERVAL 0.2f - -extern Transport transport; -extern char *instance_name; - -extern NSM_Client *nsm; - -extern UI *ui; - -NSM_Client::NSM_Client ( ) -{ - project_filename = 0; -} - -int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); -int command_save ( char **out_msg ); - - -int -NSM_Client::command_save ( char **out_msg ) -{ - save_song( nsm->project_filename ); - return ERR_OK; -} - -int -NSM_Client::command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ) -{ - if ( transport.rolling ) - { - *out_msg = strdup( "Cannot open while transport is running." ); - - return ERR_NOT_NOW; - } - - if ( song.dirty() ) - { - *out_msg = strdup( "Song has unsaved changes!" ); - - return ERR_UNSAVED_CHANGES; - } - - if ( instance_name ) - free( instance_name ); - - instance_name = strdup( client_id ); - - if ( ! midi_is_active() ) - { - setup_jack(); - } - else - { - midi_all_sound_off(); - midi_shutdown(); - setup_jack(); - } - - char *new_filename; - - asprintf( &new_filename, "%s.non", name ); - - struct stat st; - - if ( 0 == stat( new_filename, &st ) ) - { - if ( ! load_song( new_filename ) ) - { - *out_msg = strdup( "Could not open file" ); - return ERR_GENERAL; - } - } - else - { - save_song( new_filename ); - } - - if ( nsm->project_filename ) - free( nsm->project_filename ); - - nsm->project_filename = new_filename; - - return ERR_OK; -} - -void -NSM_Client::command_active ( bool b ) -{ - if ( b ) - { - ui->sm_indicator->value( 1 ); - ui->sm_indicator->tooltip( session_manager_name() ); - } - else - { - ui->sm_indicator->tooltip( NULL ); - ui->sm_indicator->value( 0 ); - } -} diff --git a/sequencer/src/NSM.H b/sequencer/src/NSM.H deleted file mode 100644 index 0f787d8..0000000 --- a/sequencer/src/NSM.H +++ /dev/null @@ -1,41 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "NSM/Client.H" - -class NSM_Client : public NSM::Client -{ - - char *project_filename; - -public: - - NSM_Client ( ); - ~NSM_Client ( ) { }; - -protected: - - int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ); - int command_save ( char **out_msg ); - int command_quit ( char **out_msg ); - - void command_active ( bool ); -}; diff --git a/sequencer/src/NSM/Client.C b/sequencer/src/NSM/Client.C deleted file mode 100644 index fae4b9c..0000000 --- a/sequencer/src/NSM/Client.C +++ /dev/null @@ -1,298 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../debug.h" -#include "Client.H" -#include -#include -#include -#include - -#pragma GCC diagnostic ignored "-Wunused-parameter" - -namespace NSM -{ - -/************************/ -/* OSC Message Handlers */ -/************************/ - -#undef OSC_REPLY -#undef OSC_REPLY_ERR - -#define OSC_REPLY( value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/reply", "ss", path, value ) - -#define OSC_REPLY_ERR( errcode, value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/error", "sis", path, errcode, value ) - - Client::Client ( ) - { - nsm_addr = 0; - nsm_client_id = 0; - _session_manager_name = 0; - nsm_is_active = false; - _server = 0; - _st = 0; - } - - Client::~Client ( ) - { - if ( _st ) - stop(); - - if ( _st ) - lo_server_thread_free( _st ); - else - lo_server_free ( _server ); - } - - void - Client::announce ( const char *application_name, const char *capabilities, const char *process_name ) - { - MESSAGE( "Announcing to NSM" ); - - lo_address to = lo_address_new_from_url( nsm_url ); - - if ( ! to ) - { - MESSAGE( "Bad address" ); - return; - } - - int pid = (int)getpid(); - - lo_send_from( to, _server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii", - application_name, - capabilities, - process_name, - 1, /* api_major_version */ - 0, /* api_minor_version */ - pid ); - - lo_address_free( to ); - } - - void - Client::progress ( float p ) - { - if ( nsm_is_active ) - { - lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", p ); - } - } - - void - Client::is_dirty ( void ) - { - if ( nsm_is_active ) - { - lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_dirty", "" ); - } - } - - void - Client::is_clean ( void ) - { - if ( nsm_is_active ) - { - lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_clean", "" ); - } - } - - void - Client::message ( int priority, const char *msg ) - { - if ( nsm_is_active ) - { - lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, msg ); - } - } - - - void - Client::broadcast ( lo_message msg ) - { - if ( nsm_is_active ) - { - lo_send_message_from( nsm_addr, _server, "/nsm/server/broadcast", msg ); - } - } - - void - Client::check ( int timeout ) - { - if ( lo_server_wait( _server, timeout ) ) - while ( lo_server_recv_noblock( _server, 0 ) ) {} - } - - void - Client::start ( ) - { - lo_server_thread_start( _st ); - } - - void - Client::stop ( ) - { - lo_server_thread_stop( _st ); - } - - int - Client::init ( const char *nsm_url ) - { - this->nsm_url = nsm_url; - - lo_address addr = lo_address_new_from_url( nsm_url ); - int proto = lo_address_get_protocol( addr ); - lo_address_free( addr ); - - _server = lo_server_new_with_proto( NULL, proto, NULL ); - - if ( ! _server ) - return -1; - - lo_server_add_method( _server, "/error", "sis", &Client::osc_error, this ); - lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this ); - lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this ); - lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this ); - lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); - lo_server_add_method( _server, NULL, NULL, &Client::osc_broadcast, this ); - - return 0; - } - - int - Client::init_thread ( const char *nsm_url ) - { - this->nsm_url = nsm_url; - - lo_address addr = lo_address_new_from_url( nsm_url ); - int proto = lo_address_get_protocol( addr ); - lo_address_free( addr ); - - _st = lo_server_thread_new_with_proto( NULL, proto, NULL ); - _server = lo_server_thread_get_server( _st ); - - if ( ! _server || ! _st ) - return -1; - - lo_server_thread_add_method( _st, "/error", "sis", &Client::osc_error, this ); - lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this ); - lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this ); - lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this ); - lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); - lo_server_thread_add_method( _st, NULL, NULL, &Client::osc_broadcast, this ); - - return 0; - } - -/************************/ -/* OSC Message Handlers */ -/************************/ - - int - Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - return ((NSM::Client*)user_data)->command_broadcast( path, msg ); - } - - int - Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - char *out_msg = NULL; - - int r = ((NSM::Client*)user_data)->command_save(&out_msg); - - if ( r ) - OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") ); - else - OSC_REPLY( "OK" ); - - if ( out_msg ) - free( out_msg ); - - return 0; - } - - int - Client::osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - char *out_msg = NULL; - - NSM::Client *nsm = (NSM::Client*)user_data; - - nsm->nsm_client_id = strdup( &argv[2]->s ); - - int r = ((NSM::Client*)user_data)->command_open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg); - - if ( r ) - OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") ); - else - OSC_REPLY( "OK" ); - - if ( out_msg ) - free( out_msg ); - - return 0; - } - - int - Client::osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - NSM::Client *nsm = (NSM::Client*)user_data; - - nsm->command_session_is_loaded(); - - return 0; - } - - int - Client::osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) ) - return -1; - - NSM::Client *nsm = (NSM::Client*)user_data; - - - WARNING( "Failed to register with NSM: %s", &argv[2]->s ); - nsm->nsm_is_active = false; - - nsm->command_active( nsm->nsm_is_active ); - - return 0; - } - - int - Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) - { - if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) ) - return -1; - - NSM::Client *nsm = (NSM::Client*)user_data; - - MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s ); - nsm->nsm_is_active = true; - nsm->_session_manager_name = strdup( &argv[2]->s ); - nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) )); - - nsm->command_active( nsm->nsm_is_active ); - - return 0; - } -}; diff --git a/sequencer/src/NSM/Client.H b/sequencer/src/NSM/Client.H deleted file mode 100644 index f417944..0000000 --- a/sequencer/src/NSM/Client.H +++ /dev/null @@ -1,109 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -namespace NSM -{ - - class Client - { - - private: - - const char *nsm_url; - - lo_server _server; - lo_server_thread _st; - lo_address nsm_addr; - - bool nsm_is_active; - char *nsm_client_id; - char *_session_manager_name; - - public: - - enum - { - ERR_OK = 0, - ERR_GENERAL = -1, - ERR_INCOMPATIBLE_API = -2, - ERR_BLACKLISTED = -3, - ERR_LAUNCH_FAILED = -4, - ERR_NO_SUCH_FILE = -5, - ERR_NO_SESSION_OPEN = -6, - ERR_UNSAVED_CHANGES = -7, - ERR_NOT_NOW = -8 - }; - - Client ( ); - virtual ~Client ( ); - - bool is_active ( void ) { return nsm_is_active; } - - const char *session_manager_name ( void ) { return _session_manager_name; } - - /* Client->Server methods */ - void is_dirty ( void ); - void is_clean ( void ); - void progress ( float f ); - void message( int priority, const char *msg ); - void announce ( const char *appliction_name, const char *capabilities, const char *process_name ); - - void broadcast ( lo_message msg ); - - /* init without threading */ - int init ( const char *nsm_url ); - /* init with threading */ - int init_thread ( const char *nsm_url ); - - /* call this periodically to check for new messages */ - void check ( int timeout = 0 ); - - /* or call these to start and stop a thread (must do your own locking in handler!) */ - void start ( void ); - void stop ( void ); - - protected: - - /* Server->Client methods */ - virtual int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ) = 0; - virtual int command_save ( char **out_msg ) = 0; - - virtual void command_active ( bool ) { } - - virtual void command_session_is_loaded ( void ) { } - - /* invoked when an unrecognized message is received. Should return 0 if you handled it, -1 otherwise. */ - virtual int command_broadcast ( const char *, lo_message ) { return -1; } - - private: - - /* osc handlers */ - static int osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - - }; -}; diff --git a/sequencer/src/canvas.C b/sequencer/src/canvas.C deleted file mode 100644 index ba3509a..0000000 --- a/sequencer/src/canvas.C +++ /dev/null @@ -1,1897 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* This is a generic double-buffering, optimizing canvas interface to - grids (patterns and phrases). It draws only what is necessary to keep - the display up-to-date. Actual drawing functions are in draw.C */ -#include -#include - -#include "canvas.H" -#include "pattern.H" -#include "common.h" - -#include "non.H" -#include -#include -#include "gui/ui.H" -#include -#include - -using namespace MIDI; -extern UI *ui; - -extern Fl_Color velocity_colors[]; -const int ruler_height = 14; - - - - -class Canvas::Canvas_Panzoomer : public Fl_Panzoomer -{ - Fl_Offscreen backbuffer; - -public: - - Canvas_Panzoomer( int X, int Y,int W, int H, const char *L = 0 ) - : Fl_Panzoomer(X,Y,W,H,L) - { - backbuffer = 0; - } - - Canvas *canvas; - -private: - - static void draw_dash ( tick_t x, int y, tick_t l, int color, int selected, void *userdata ) - { - Canvas_Panzoomer *o = (Canvas_Panzoomer*)userdata; - - o->draw_dash( x,y,l,color,selected ); - } - - void draw_dash ( tick_t x, int y, tick_t w, int color, int selected ) const - { - if ( selected ) - color = FL_MAGENTA; - else - color = velocity_colors[ color ]; - - Canvas *c = canvas; - - double VS = (double)this->h() / c->m.maxh; - double HS = (double)this->w() / ( _xmax - _xmin ); - - y = c->ntr( y ); - - if ( y < 0 ) - return; - - y *= VS; - - fl_color( fl_color_average( color, FL_GRAY, 0.5 ) ); - - fl_rectf( - x * HS, - y, - (w * HS) + 0.5, - 1 * VS + 0.5 ); - } - -protected: - - void draw_background ( int X, int Y, int W, int H ) - { - - /* DMESSAGE( "%s%s%s%s%s%s", */ - /* damage() & FL_DAMAGE_CHILD ? "CHILD " : "", */ - /* damage() & FL_DAMAGE_ALL ? "ALL " : "", */ - /* damage() & FL_DAMAGE_USER1 ? "USER 1 ": "", */ - /* damage() & FL_DAMAGE_EXPOSE ? "EXPOSE " : "", */ - /* damage() & FL_DAMAGE_SCROLL ? "SCROLL " : "", */ - /* damage() & FL_DAMAGE_OVERLAY ? "OVERLAY " : ""); */ - - if ( ! backbuffer || - ! ( damage() & FL_DAMAGE_USER1 ) ) - { - if ( !backbuffer ) - backbuffer = fl_create_offscreen( W, H ); - - DMESSAGE( "redrawing preview" ); - - fl_begin_offscreen(backbuffer); - - fl_rectf( 0, 0, W, H, color() ); - canvas->m.grid->draw_notes( draw_dash, this ); - - fl_end_offscreen(); - } - - fl_copy_offscreen( X,Y,W,H,backbuffer,0, 0 ); - } -public: - - void resize ( int X, int Y, int W, int H ) - { - Fl_Panzoomer::resize( X,Y,W,H ); - if ( backbuffer ) - fl_delete_offscreen( backbuffer ); - backbuffer = 0; - redraw(); - } - - void draw_overlay ( void ) - { - Canvas *c = canvas; - - double HS = (double)w() /( _xmax - _xmin ); - - tick_t new_x = c->grid()->x_to_ts( c->grid()->ts_to_x( c->grid()->index() ) ); - fl_color( fl_color_add_alpha( FL_RED, 100 ) ); - fl_line( x() + new_x * HS, y(), x() + new_x * HS, y() + h() ); - } - -}; - -static note_properties *ghost_note = 0; - -Canvas::Canvas ( int X, int Y, int W, int H, const char *L ) : Fl_Group( X,Y,W,H,L ) -{ - _selection_mode = SELECT_NONE; - _move_mode = false; - - { Fl_Box *o = new Fl_Box( X, Y, W, H - 75 ); - /* this is a dummy group where the canvas goes */ - Fl_Group::current()->resizable( o ); - } - { Fl_Group *o = new Fl_Group( X, Y + H - 75, W, 75 ); - - { - Canvas_Panzoomer *o = new Canvas_Panzoomer( X, Y + H - 75, W - 14, 75 ); - o->canvas = this; - o->box( FL_FLAT_BOX ); -// o->color(fl_color_average( FL_BLACK, FL_WHITE, 0.90 )); - o->color( FL_BLACK ); -// o->color(FL_BACKGROUND_COLOR); -// o->type( FL_HORIZONTAL ); - o->callback( cb_scroll, this ); - o->when( FL_WHEN_CHANGED ); - panzoomer = o; - } - - { - Fl_Slider *o = new Fl_Slider( X + W - 14, Y + H - panzoomer->h(), 14, panzoomer->h() ); - o->range( 1, 128 ); - o->step( 1 ); - o->type( FL_VERTICAL ); - o->tooltip( "Vertical Zoom" ); - o->callback( cb_scroll, this ); - vzoom = o; - } - o->end(); - } - - m.origin_x = m.origin_y = m.height = m.width = m.div_w = m.div_h = m.margin_top = m.margin_left = m.playhead = m.w = m.h = m.p1 = m.p2 = m.p3 = m.p4 = 0; - - m.margin_top = ruler_height; - - m.draw = false; - m.ruler_drawn = false; - m.grid_drawn = false; - -// m.current = m.previous = NULL; - - m.row_compact = true; - - m.maxh = 128; - - m.vp = NULL; - - m.grid = NULL; - - end(); - - resize( X,Y,W,H); -} - -Canvas::~Canvas ( ) -{ - -} - -void -Canvas::handle_event_change ( void ) -{ - /* mark the song as dirty and pass the signal on */ - song.set_dirty(); - - Grid *g = grid(); - panzoomer->x_value( g->x_to_ts( m.vp->x), g->x_to_ts( m.vp->w ), 0, g->length()); - - // panzoomer->redraw(); - - redraw(); -} - -/** change grid to /g/, returns TRUE if new grid size differs from old */ -void -Canvas::grid ( Grid *g ) -{ - m.grid = g; - - if ( ! g ) - return; - - m.vp = &g->viewport; - - char *s = m.vp->dump(); - DMESSAGE( "viewport: %s", s ); - free( s ); - - m.ruler_drawn = false; - - resize_grid(); - - vzoom->range( 1, m.maxh ); - vzoom->value( m.vp->h ); - - update_mapping(); - - /* connect signals */ - /* FIXME: what happens when we do this twice? */ - g->signal_events_change.connect( mem_fun( this, &Canvas::handle_event_change ) ); - g->signal_settings_change.connect( signal_settings_change.make_slot() ); - - redraw(); - -// parent()->redraw(); - signal_settings_change(); -} - -/** keep row compaction tables up-to-date */ -void -Canvas::_update_row_mapping ( void ) -{ - /* reset */ - for ( int i = 128; i-- ; ) - m.rtn[i] = m.ntr[i] = -1; - - DMESSAGE( "updating row mapping" ); - - /* rebuild */ - int r = 0; - for ( int n = 0; n < 128; ++n ) - { - if ( m.grid->row_name( n ) ) - { - m.rtn[r] = n; - m.ntr[n] = r; - ++r; - } - } - - if ( m.row_compact && r ) - m.maxh = r; - else - m.maxh = 128; - - m.vp->h = min( m.vp->h, m.maxh ); - - resize_grid(); -} - -/** update everything about mapping, leaving the viewport alone */ -void -Canvas::update_mapping ( void ) -{ - _update_row_mapping(); - - adj_size(); - -// int old_margin = m.margin_left; - - m.margin_left = 0; - - m.draw = false; - - m.grid->draw_row_names( this ); - - m.draw = true; - -/* if ( m.margin_left != old_margin ) */ -/* { */ -/* // signal_resize(); */ -/* redraw(); */ -/* } */ -/* else */ - - damage(FL_DAMAGE_USER1); - -} - -/** change grid mapping */ -void -Canvas::changed_mapping ( void ) -{ - update_mapping(); - - m.vp->h = min( m.vp->h, m.maxh ); - - if ( m.vp->y + m.vp->h > m.maxh ) - m.vp->y = (m.maxh / 2) - (m.vp->h / 2); -} - -Grid * -Canvas::grid ( void ) -{ - return m.grid; -} - - -/** recalculate node sizes based on physical dimensions */ -void -Canvas::adj_size ( void ) -{ - if ( ! m.vp ) - return; - - m.div_w = (m.width - m.margin_left) / m.vp->w; - m.div_h = (m.height - m.margin_top) / m.vp->h; -} - -/** reallocate buffers to match grid dimensions */ -void -Canvas::resize_grid ( void ) -{ - adj_size(); - - DMESSAGE( "resizing grid %dx%d", m.vp->w, m.vp->h ); - - Grid *g = grid(); - panzoomer->x_value( g->x_to_ts( m.vp->x), g->x_to_ts( m.vp->w ), 0, g->length()); - panzoomer->y_value( m.vp->y, m.vp->h, 0, m.maxh ); - - panzoomer->zoom_range( 2, 16 ); - -// m.vp->w = max( 32, min( (int)(m.vp->w * n), 256 ) ); - -} - -/** inform the canvas with new phsyical dimensions */ -void -Canvas::resize ( int x, int y, int w, int h ) -{ - m.origin_x = x; - m.origin_y = y; - - m.width = w; - m.height = h - 75; - - Fl_Group::resize(x,y,w,h); - - adj_size(); -} - - - -/***********/ -/* Drawing */ -/***********/ - -/** is /x/ within the viewport? */ -bool -Canvas::viewable_x ( int x ) -{ - return x >= m.vp->x && x < m.vp->x + m.vp->w; -} - -static -int -gui_draw_ruler ( int x, int y, int w, int div_w, int div, int ofs, int p1, int p2 ) -{ - /* Across the top */ - - - fl_font( FL_TIMES, ruler_height ); - - int h = ruler_height; - - fl_color( FL_BACKGROUND_COLOR ); - - w += 100; /* FIXME: hack */ - - // fl_rectf( x, y, x + (div_w * w), y + h ); - fl_rectf( x, y, (div_w * w), h ); - - - fl_color( FL_FOREGROUND_COLOR ); - - fl_line( x + div_w / 2, y, x + div_w * w, y ); - - char pat[40]; - int z = div; - int i; - for ( i = 0; i < w; i++ ) - { - int k = ofs + i; - if ( 0 == k % z ) - { - int nx = x + (i * div_w) + (div_w / 2); - - fl_color( FL_FOREGROUND_COLOR ); - - fl_line( nx, y, nx, y + h - 1 ); - - sprintf( pat, "%i", 1 + (k / z )); - - fl_color( FL_FOREGROUND_COLOR ); - fl_draw( pat, nx + div_w / 2, y + h + 1 / 2 ); - } - } - - if ( p1 != p2 ) - { - if ( p1 >= 0 ) - { - if ( p1 < p2 ) - fl_color( fl_color_add_alpha( FL_GREEN, 100 ) ); - else - fl_color( fl_color_add_alpha( FL_GREEN, 100 ) ); - - fl_rectf( x + (div_w * p1), y + h / 2, div_w, h / 2 ); - - } - if ( p2 >= 0 ) - { - if ( p2 < p1 ) - fl_color( fl_color_add_alpha( FL_GREEN, 100 ) ); - else - fl_color( fl_color_add_alpha( FL_RED, 100 ) ); - fl_rectf( x + (div_w * p2), y + h / 2, div_w, h / 2 ); - - } - } - - return h; -} - -static -int -gui_draw_string ( int x, int y, int w, int h, int color, const char *s, bool draw ) -{ - int rw; - - if ( ! s ) - return 0; - - fl_font( FL_COURIER, min( h, 18 ) ); - - rw = fl_width( s ); - - if ( fl_not_clipped( x, y, rw, h ) && draw ) - { -// fl_rectf( x,y,w,h, FL_BACKGROUND_COLOR ); - - if ( color ) - fl_color( velocity_colors[ color ] ); - else - fl_color( FL_DARK_CYAN ); - - fl_draw( s, x, y + h / 2 + fl_descent() ); - } - - return rw; -} - -/** callback called by Grid::draw_row_names() to draw an individual row name */ -void -Canvas::draw_row_name ( int y, const char *name, int color ) -{ - bool draw = m.draw; - - y = ntr( y ); - - y -= m.vp->y; - - int bx = m.origin_x; - int by = m.origin_y + m.margin_top + y * m.div_h; - int bw = m.margin_left; - int bh = m.div_h; - - if ( y < 0 || y >= m.vp->h ) - draw = false; - - if ( draw && name ) - { - fl_rectf( bx, by, bw, bh, index(name, '#') ? FL_GRAY : FL_BLACK ); - fl_rect( bx, by, bw, bh, FL_BLACK ); - } - - m.margin_left = max( m.margin_left, gui_draw_string( bx + 1, by + 2, - bw - 1, bh - 4, - color, - name, - draw ) ); -} - -void -Canvas::draw_mapping ( void ) -{ -// int old_margin = m.margin_left; - - m.margin_left = 0; - - m.draw = false; - - m.grid->draw_row_names( this ); - - adj_size(); - - m.draw = true; - - m.grid->draw_row_names( this ); -} - -void -Canvas::draw_ruler ( void ) -{ - m.margin_top = gui_draw_ruler( m.origin_x + m.margin_left, - m.origin_y, - m.vp->w, - m.div_w, - m.grid->division(), - m.vp->x, - m.p1 - m.vp->x, - m.p2 - m.vp->x ); -} - -void -Canvas::damage_grid ( tick_t x, int y, tick_t w, int h = 1 ) -{ - y = ntr( y ); - - if ( y < 0 ) - return; - - // adjust for viewport. - - x = m.grid->ts_to_x(x); - w = m.grid->ts_to_x(w); - - x -= m.vp->x; - y -= m.vp->y; - - if ( x < 0 || y < 0 || x >= m.vp->w || y >= m.vp->h ) - return; - - damage(FL_DAMAGE_USER1, m.origin_x + m.margin_left + x * m.div_w, - m.origin_y + m.margin_top + y * m.div_h, - m.div_w * w, - m.div_h * h ); -} - -void -Canvas::draw_dash ( tick_t x, int y, tick_t w, int color, int selected ) const -{ - if ( m.grid->velocity_sensitive() ) - color = velocity_colors[ color ]; - else - color = velocity_colors[ 127 ]; - - y = ntr( y ); - - if ( y < 0 ) - return; - - // adjust for viewport. - - x = m.grid->ts_to_x(x); - w = m.grid->ts_to_x(w); - - x -= m.vp->x; - y -= m.vp->y; - - x = m.origin_x + m.margin_left + x * m.div_w; - y = m.origin_y + m.margin_top + y * m.div_h; - w *= m.div_w; - - /* fl_rectf( x, y + 1, w, m.div_h - 1, fl_color_add_alpha( color, 170 ) ); */ - - /* fl_rect( x, y + 1, w, m.div_h - 1, selected ? FL_MAGENTA : fl_lighter( FL_BACKGROUND_COLOR )); */ - - if ( w > 4 ) - { - fl_draw_box( FL_ROUNDED_BOX, x, y + 1, w, m.div_h - 1, color ); - - if ( selected ) - { - cairo_set_operator( Fl::cairo_cc(),CAIRO_OPERATOR_HSL_COLOR ); - - fl_draw_box( FL_ROUNDED_BOX, x, y + 1, w, m.div_h - 1, FL_MAGENTA ); - - cairo_set_operator( Fl::cairo_cc(),CAIRO_OPERATOR_OVER); - } - /* if ( selected ) */ - /* fl_draw_box( FL_ROUNDED_FRAME, x, y + 1, w, m.div_h - 1, FL_MAGENTA ); */ - } - -// fl_color_add_alpha( color, 170 )); -} - -/** callback used by Grid::draw() */ -void -Canvas::draw_dash ( tick_t x, int y, tick_t w, int color, int selected, void *userdata ) -{ - Canvas *o = (Canvas*)userdata; - - o->draw_dash( x,y,w,color,selected ); -} - -int -Canvas::playhead_moved ( void ) -{ - int x = m.grid->ts_to_x( m.grid->index() ); - - return m.playhead != x; -} - -void -Canvas::redraw_playhead ( void ) -{ - int old_x = m.playhead; - - int new_x = m.grid->ts_to_x( m.grid->index() ); - - if ( old_x != new_x ) - { - window()->damage( FL_DAMAGE_OVERLAY ); - } - - if ( m.playhead < m.vp->x || m.playhead >= m.vp->x + m.vp->w ) - { - if ( config.follow_playhead ) - { - new_x = m.playhead; - - panzoomer->x_value( m.grid->index() ); - panzoomer->do_callback(); - } - } -} - -void -Canvas::draw_overlay ( void ) -{ - if ( ! visible_r() ) - return; - - /* fl_push_no_clip(); */ - - fl_push_clip( x() + m.margin_left, - y() + m.margin_top, - w() - m.margin_left, - h() - panzoomer->h() - m.margin_top ); - - draw_playhead(); - - if ( _selection_mode ) - { - int X,Y,W,H; - - SelectionRect &s = _selection_rect; - - X = s.x1 < s.x2 ? s.x1 : s.x2; - Y = s.y1 < s.y2 ? s.y1 : s.y2; - W = s.x1 < s.x2 ? s.x2 - s.x1 : s.x1 - s.x2; - H = s.y1 < s.y2 ? s.y2 - s.y1 : s.y1 - s.y2; - - /* fl_rectf( X,Y,W,H, fl_color_add_alpha( FL_MAGENTA, 50 ) ); */ - - fl_rect( X,Y,W,H, FL_MAGENTA ); - - } - - fl_pop_clip(); - - panzoomer->draw_overlay(); - - /* fl_pop_clip(); */ - -} - -/** draw only the playhead--without reexamining the grid */ -void -Canvas::draw_playhead ( void ) -{ - int x = m.grid->ts_to_x( m.grid->index() ); - - /* if ( m.playhead == x ) */ - /* return; */ - - m.playhead = x; - - /* if ( m.playhead < m.vp->x || m.playhead >= m.vp->x + m.vp->w ) */ - /* return; */ - - int px = m.origin_x + m.margin_left + ( x - m.vp->x ) * m.div_w; - - int X,Y,W,H; - - X = px; - Y = m.origin_y + m.margin_top; - W = m.div_w; - H = m.origin_y + m.margin_top + m.vp->h * m.div_h; - - cairo_set_operator( Fl::cairo_cc(), CAIRO_OPERATOR_HSL_COLOR ); - - fl_rectf( X,Y,W,H, FL_RED ); - - cairo_set_operator( Fl::cairo_cc(), CAIRO_OPERATOR_OVER ); - - fl_rect( X,Y,W,H, FL_RED ); -} - -void -Canvas::draw_clip ( void *v, int X, int Y, int W, int H ) -{ - ((Canvas*)v)->draw_clip( X,Y,W,H ); -} - -void -Canvas::draw_clip ( int X, int Y, int W, int H ) -{ - box( FL_FLAT_BOX ); - labeltype( FL_NO_LABEL ); - - fl_push_clip( X,Y,W,H ); - - - fl_push_clip( m.origin_x + m.margin_left, - m.origin_y + m.margin_top, - w() - m.margin_left, - h() - m.margin_top - panzoomer->h() ); - - fl_rectf( m.origin_x + m.margin_left, m.origin_y + m.margin_top, w(), h(), FL_BLACK ); - - /* draw bar/beat lines */ - - for ( int gx = m.vp->x; - gx < m.vp->x + m.vp->w + 200; /* hack */ - gx++ ) - { - if ( m.grid->x_to_ts( gx ) > m.grid->length() ) - continue; - - if ( gx % m.grid->division() == 0 ) - fl_color( fl_color_average( FL_GRAY, FL_BLACK, 0.80 ) ); - else if ( gx % m.grid->subdivision() == 0 ) - fl_color( fl_color_average( FL_GRAY, FL_BLACK, 0.40 ) ); - else - continue; - - fl_rectf( m.origin_x + m.margin_left + ( ( gx - m.vp->x ) * m.div_w ), - m.origin_y + m.margin_top, - m.div_w, - y() + h() - m.margin_top ); - } - - m.grid->draw_notes( draw_dash, this ); - - if ( ghost_note ) - draw_dash( ghost_note->start, - ghost_note->note, - ghost_note->duration, - ghost_note->velocity, - 1 ); - - fl_color( fl_color_add_alpha( fl_rgb_color( 127,127,127 ), 50 )); - - /* draw grid */ - - fl_begin_line(); - - if ( m.div_w > 4 ) - { - for ( int gx = m.origin_x + m.margin_left; - gx < x() + w(); - gx += m.div_w ) - { -// fl_line( gx, m.origin_y + m.margin_top, gx, y() + h() ); - fl_vertex( gx, m.origin_y + m.margin_top ); - fl_vertex( gx, y() + h() ); - fl_gap(); - } - } - - if ( m.div_h > 2 ) - { - for ( int gy = m.origin_y + m.margin_top; - gy < y() + h(); - gy += m.div_h ) - { -// fl_line( m.origin_x + m.margin_left, gy, x() + w(), gy ); - fl_vertex( m.origin_x + m.margin_left, gy ); - fl_vertex( x() + w(), gy ); - fl_gap(); - } - } - - fl_end_line(); - -//done: - fl_pop_clip(); - - fl_pop_clip(); -} - - -/** draw ONLY those nodes necessary to bring the canvas up-to-date with the grid */ -void -Canvas::draw ( void ) -{ - box( FL_NO_BOX ); - labeltype( FL_NO_LABEL ); - - /* DMESSAGE( "%s%s%s%s%s%s", */ - /* damage() & FL_DAMAGE_CHILD ? "CHILD " : "", */ - /* damage() & FL_DAMAGE_ALL ? "ALL " : "", */ - /* damage() & FL_DAMAGE_USER1 ? "USER 1 ": "", */ - /* damage() & FL_DAMAGE_EXPOSE ? "EXPOSE " : "", */ - /* damage() & FL_DAMAGE_SCROLL ? "SCROLL " : "", */ - /* damage() & FL_DAMAGE_OVERLAY ? "OVERLAY " : ""); */ - - - if ( damage() & FL_DAMAGE_SCROLL ) - { - draw_ruler(); - - int dx = ( _old_scroll_x - m.vp->x ) * m.div_w; - int dy = ( _old_scroll_y - m.vp->y ) * m.div_h; - - fl_scroll( m.origin_x + m.margin_left, - m.origin_y + m.margin_top, - w() - m.margin_left, - h() - m.margin_top - panzoomer->h(), - dx, dy, - draw_clip, - this ); - - if ( dy ) - draw_mapping(); - - _old_scroll_x = m.vp->x; - _old_scroll_y = m.vp->y; - - if ( damage() & FL_DAMAGE_CHILD ) - clear_damage( FL_DAMAGE_CHILD ); - } - else if ( damage() & ~FL_DAMAGE_CHILD ) - { - draw_mapping(); - draw_ruler(); - - draw_clip( x(), y(), w(), h() ); - } - - draw_children(); -} - -void -Canvas::cb_scroll ( Fl_Widget *w, void *v ) -{ - ((Canvas*)v)->cb_scroll( w ); -} - -void -Canvas::cb_scroll ( Fl_Widget *w ) -{ - if ( w == panzoomer ) - { - Fl_Panzoomer *o = (Fl_Panzoomer*)w; - - _old_scroll_x = m.vp->x; - _old_scroll_y = m.vp->y; - - m.vp->x = grid()->ts_to_x( o->x_value() ); - m.vp->y = o->y_value(); - - if ( m.vp->x != _old_scroll_x || m.vp->y != _old_scroll_y ) - damage( FL_DAMAGE_SCROLL ); - - if ( o->zoom_changed() ) - { - m.vp->w = m.grid->division() * o->zoom(); - resize_grid(); - redraw(); - } - } - else if ( w == vzoom ) - { - Fl_Slider *o = (Fl_Slider*)w; - - float n = o->value(); - - m.vp->h = min( (int)n, m.maxh ); - - resize_grid(); - - song.set_dirty(); - - redraw(); - } - -} - - -/** convert pixel coords into grid coords. returns true if valid */ -bool -Canvas::grid_pos ( int *x, int *y ) const -{ - /* if ( ( *x < m.origin_x + m.margin_left ) || */ - /* ( *y < m.origin_y + m.margin_top ) || */ - /* ( *x > m.origin_x + w() ) || */ - /* (*y > m.origin_y + h() - panzoomer->h() ) ) */ - /* return false; */ - - *y = (*y - m.margin_top - m.origin_y) / m.div_h; - *x = (*x - m.margin_left - m.origin_x) / m.div_w; - - /* if ( *x < 0 || *y < 0 || *x >= m.vp->w || *y >= m.vp->h ) */ - /* return false; */ - - /* adjust for viewport */ - *x += m.vp->x; - *y += m.vp->y; - - /* adjust for row-compaction */ - *y = rtn( *y ); - - return true; -} - - - -/******************/ -/* Input handlers */ -/******************/ - -/* These methods translate viewport pixel coords to absolute grid - coords and pass on to the grid. */ - -/** if coords correspond to a row name entry, return the (absolute) note number, otherwise return -1 */ -int -Canvas::is_row_press ( void ) const -{ - if ( Fl::event_inside( this->x(), - this->y() + this->m.margin_top, - this->m.margin_left, - ( this->h() - this->m.margin_top ) - this->panzoomer->h() ) ) - { - int dx,dy; - dx = Fl::event_x(); - dy = Fl::event_y(); - - grid_pos( &dx, &dy ); - - return m.grid->y_to_note(dy ); - } - else - return -1; -} - -bool -Canvas::is_ruler_click ( void ) const -{ - return Fl::event_y() < m.origin_y + m.margin_top; -} - -void -Canvas::start_cursor ( int x, int y ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.ruler_drawn = false; - - m.p1 = x; - - - /* m.p3 = ntr( y ); */ - - _lr(); - - redraw(); -} - -void -Canvas::end_cursor ( int x, int y ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.ruler_drawn = false; - - m.p2 = x; - - /* m.p4 = ntr( y ); */ - - _lr(); - - redraw(); -} - -void -Canvas::adj_color ( int x, int y, int n ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.grid->adj_velocity( x, y, n ); -} - -void -Canvas::adj_length ( int x, int y, int n ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.grid->adj_duration( x, y, n ); -} - -void -Canvas::set_end ( int x, int y, int n ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.grid->set_end( x, y, n ); -} - -void -Canvas::select ( int x, int y ) -{ - if ( ! grid_pos( &x, &y ) ) - return; - - m.grid->toggle_select( x, y ); -} - -void -Canvas::move_selected ( int dir, int n ) -{ - switch ( dir ) - { - case RIGHT: - m.grid->nudge_selected( n ); - break; - case LEFT: - m.grid->nudge_selected( 0 - n ); - break; - case UP: - case DOWN: - { - /* row-compaction makes this a little complicated */ - event_list *el = m.grid->events(); - - /* FIXME: don't allow movement beyond the edges! */ - -/* int hi, lo; */ - -/* m.grid->selected_hi_lo_note( &hi, &lo ); */ - -/* hi = ntr( hi ) > 0 ? ntr( hi ) : */ - -/* if ( m.grid->y_to_note( ntr( hi ) ) ) */ - - - if ( dir == UP ) - for ( int y = 0; y <= m.maxh; ++y ) - el->rewrite_selected( m.grid->y_to_note( rtn( y ) ), m.grid->y_to_note( rtn( y - n ) ) ); - else - for ( int y = m.maxh; y >= 0; --y ) - el->rewrite_selected( m.grid->y_to_note( rtn( y ) ), m.grid->y_to_note( rtn( y + n ) ) ); - - m.grid->events( el ); - - delete el; - break; - } - } -} - -void -Canvas::_lr ( void ) -{ - int l, r; - - if ( m.p2 > m.p1 ) - { - l = m.p1; - r = m.p2; - } - else - { - l = m.p2; - r = m.p1; - } - - m.p1 = l; - m.p2 = r; -} - -void -Canvas::select_range ( void ) -{ - if ( m.p3 == m.p4 ) - m.grid->select( m.p1, m.p2 ); - else - m.grid->select( m.p1, m.p2, rtn( m.p3 ), rtn( m.p4 ) ); -} - -void -Canvas::invert_selection ( void ) -{ - m.grid->invert_selection(); -} - -void -Canvas::crop ( void ) -{ - if ( m.p3 == m.p4 ) - m.grid->crop( m.p1, m.p2 ); - else - m.grid->crop( m.p1, m.p2, rtn( m.p3 ), rtn( m.p4 ) ); - - m.vp->x = 0; - - m.p2 = m.p2 - m.p1; - m.p1 = 0; - - m.ruler_drawn = false; -} - -void -Canvas::delete_time ( void ) -{ - m.grid->delete_time( m.p1, m.p2 ); -} - - -void -Canvas::insert_time ( void ) -{ - m.grid->insert_time( m.p1, m.p2 ); -} - -/** paste range as new grid */ -void -Canvas::duplicate_range ( void ) -{ - Grid *g = m.grid->clone(); - - g->crop( m.p1, m.p2 ); - g->viewport.x = 0; -} - -void -Canvas::cut ( void ) -{ - m.grid->cut(); -} - -void -Canvas::copy ( void ) -{ - m.grid->copy(); -} - -void -Canvas::paste ( void ) -{ - if ( m.p1 != m.p2 && m.p1 > m.vp->x && m.p1 < m.vp->x + m.vp->w ) - m.grid->paste( m.p1 ); - else - m.grid->paste( m.vp->x ); -} - -void -Canvas::row_compact ( int n ) -{ - switch ( n ) - { - case OFF: - m.row_compact = false; - m.maxh = 128; - break; - case ON: - m.row_compact = true; - m.vp->y = 0; - _update_row_mapping(); - break; - case TOGGLE: - row_compact( m.row_compact ? OFF : ON ); - break; - } -// _reset(); -} - -void -Canvas::pan ( int dir, int n ) -{ - - switch ( dir ) - { - case LEFT: case RIGHT: case TO_PLAYHEAD: case TO_NEXT_NOTE: case TO_PREV_NOTE: - /* handle horizontal movement specially */ - n *= m.grid->division(); - m.ruler_drawn = false; - break; - default: - n *= 5; - break; - } - - switch ( dir ) - { - case LEFT: - m.vp->x = max( m.vp->x - n, 0 ); - break; - case RIGHT: - m.vp->x += n; - break; - case TO_PLAYHEAD: - m.vp->x = m.playhead - (m.playhead % m.grid->division()); - break; - case UP: - m.vp->y = max( m.vp->y - n, 0 ); - break; - case DOWN: - m.vp->y = min( m.vp->y + n, m.maxh - m.vp->h ); - break; - case TO_NEXT_NOTE: - { - int x = m.grid->next_note_x( m.vp->x ); - m.vp->x = x - (x % m.grid->division() ); - break; - } - case TO_PREV_NOTE: - { - int x = m.grid->prev_note_x( m.vp->x ); - m.vp->x = x - (x % m.grid->division() ); - break; - } - } - - damage(FL_DAMAGE_USER1); -} - -void -Canvas::can_scroll ( int *left, int *right, int *up, int *down ) -{ - *left = m.vp->x; - *right = -1; - *up = m.vp->y; - *down = m.maxh - ( m.vp->y + m.vp->h ); -} - - -/** adjust horizontal zoom (* n) */ -void -Canvas::h_zoom ( float n ) -{ - m.vp->w = max( 32, min( (int)(m.vp->w * n), 256 ) ); - - resize_grid(); - - song.set_dirty(); -} - -void -Canvas::selected_velocity ( int v ) -{ - grid()->selected_velocity( v ); -} - -void -Canvas::v_zoom_fit ( void ) -{ - if ( ! m.grid ) - return; - - changed_mapping(); - - m.vp->h = m.maxh; - m.vp->y = 0; - - resize_grid(); - - song.set_dirty(); - -} - -/** adjust vertical zoom (* n) */ -void -Canvas::v_zoom ( float n ) -{ - m.vp->h = max( 1, min( (int)(m.vp->h * n), m.maxh ) ); - - resize_grid(); - - song.set_dirty(); -} - -void -Canvas::notes ( char *s ) -{ - m.grid->notes( s ); -} - -char * -Canvas::notes ( void ) -{ - return m.grid->notes(); -} - - -int -Canvas::handle ( int m ) -{ - Canvas *c = this; - - static int last_move_x = 0; - static int last_move_y = 0; - -// static bool range_select; - - int x, y; - int processed = 1; - - x = Fl::event_x(); - y = Fl::event_y(); - - static int drag_x; - static int drag_y; - static bool delete_note; - static note_properties *drag_note; - - switch ( m ) - { - case FL_FOCUS: - case FL_UNFOCUS: - damage( FL_DAMAGE_ALL ); - return 1; - case FL_ENTER: - case FL_LEAVE: - fl_cursor( FL_CURSOR_DEFAULT ); - return 1; - case FL_MOVE: - { - if ( Fl::event_inside( this->x() + this->m.margin_left, - this->y() + this->m.margin_top, - this->w() - this->m.margin_left, - ( this->h() - this->m.margin_top ) - this->panzoomer->h() ) ) - fl_cursor( FL_CURSOR_HAND ); - else - fl_cursor( FL_CURSOR_DEFAULT ); - - return 1; - break; - } - case FL_KEYBOARD: - { - -/* if ( Fl::event_state() & FL_ALT || Fl::event_state() & FL_CTRL ) */ -/* // this is more than a simple keypress. */ -/* return 0; */ - - if ( Fl::event_state() & FL_CTRL ) - { - switch ( Fl::event_key() ) - { - case FL_Delete: - c->delete_time(); - break; - case FL_Insert: - c->insert_time(); - break; - case FL_Right: - c->pan( TO_NEXT_NOTE, 0 ); - break; - case FL_Left: - c->pan( TO_PREV_NOTE, 0 ); - break; - default: - return 0; - } - } - else - if ( Fl::event_state() & FL_ALT ) - return 0; - - switch ( Fl::event_key() ) - { - case FL_Left: - c->pan( LEFT, 1 ); - break; - case FL_Right: - c->pan( RIGHT, 1 ); - break; - case FL_Up: - c->pan( UP, 1 ); - break; - case FL_Down: - c->pan( DOWN, 1 ); - break; - default: - /* have to do this to get shifted keys */ - switch ( *Fl::event_text() ) - { - case 'f': - c->pan( TO_PLAYHEAD, 0 ); - break; - case 'r': - c->select_range(); - break; - case 'q': - c->grid()->select_none(); - break; - case 'i': - c->invert_selection(); - break; - /* case '1': */ - /* c->h_zoom( 2.0f ); */ - /* break; */ - /* case '2': */ - /* c->h_zoom( 0.5f ); */ - /* break; */ - /* case '3': */ - /* c->v_zoom( 2.0f ); */ - /* break; */ - /* case '4': */ - /* c->v_zoom( 0.5f ); */ - /* break; */ - /* case ' ': */ - /* transport.toggle(); */ - /* break; */ - -#define IS_PATTERN (parent() == ui->pattern_tab) -#define IS_PHRASE (parent() == ui->phrase_tab) -#define IS_SEQUENCE (parent() == ui->sequence_tab) - case '<': - c->move_selected( LEFT, 1 ); - break; - case '>': - c->move_selected( RIGHT, 1 ); - break; - case ',': - c->move_selected( UP, 1 ); - break; - case '.': - c->move_selected( DOWN, 1 ); - break; - case 'C': - c->crop(); - break; - case 'd': - { - MESSAGE( "duplicating thing" ); - c->grid( c->grid()->clone() ); - - // number of phrases may have changed. - ui->update_sequence_widgets(); - - break; - - } - case 'D': - c->duplicate_range(); - break; - case 't': - c->grid()->trim(); - break; - default: - processed = 0; - break; - } - break; - } - break; - } - case FL_PUSH: - { - Fl::focus(this); - - switch ( Fl::event_button() ) - { - case 1: - { - if ( is_ruler_click() ) - { - c->start_cursor( x, y ); - // return 1; - _selection_mode = SELECT_RANGE; - - } - - if ( _selection_mode ) - { - drag_x = Fl::event_x(); - drag_y = Fl::event_y(); - - _selection_rect.x1 = drag_x; - _selection_rect.y1 = drag_y; - _selection_rect.x2 = drag_x; - _selection_rect.y2 = drag_y; - - if ( _selection_mode == SELECT_RANGE ) - { - _selection_rect.y1 = 0; - _selection_rect.y2 = 2000; - } - - return 1; - } - - delete_note = true; - - if ( Fl::event_ctrl() ) - { - c->select( x, y ); - processed = 2; - break; - } - - int dx = x; - int dy = y; - - grid_pos( &dx, &dy ); - - int note; - if ( ( note = c->is_row_press() ) >= 0 ) - { - if ( IS_PATTERN ) - ((pattern *)c->grid())->row_name_press( note ); - - processed = 2; - break; - } - - if ( Fl::event_inside( this->x() + this->m.margin_left, - this->y() + this->m.margin_top, - this->w() - this->m.margin_left, - ( this->h() - this->m.margin_top ) - this->panzoomer->h() ) ) - { - - if ( ! this->m.grid->is_set( dx,dy )) - { - ghost_note = new note_properties; - drag_note = new note_properties; - - ghost_note->start = this->m.grid->x_to_ts( dx ); - ghost_note->note = dy; - ghost_note->duration = this->m.grid->default_length(); - ghost_note->velocity = 64; - - drag_note->start = this->m.grid->x_to_ts( dx ); - drag_note->note = dy; - drag_note->duration = this->m.grid->default_length(); - drag_note->velocity = 64; - - - - delete_note = false; - - processed = 1; - break; - } - else - { - note_properties np; - this->m.grid->get_note_properties( dx, dy, &np ); - - if ( np.selected ) - { - _move_mode = true; - /* initiate move */ - last_move_x = dx; - last_move_y = ntr( dy ); - } - else - { - ghost_note = new note_properties; - drag_note = new note_properties; - this->m.grid->get_note_properties( dx, dy, ghost_note ); - this->m.grid->get_note_properties( dx, dy, drag_note ); - this->m.grid->del( dx, dy ); - - delete_note = true; - } - } - - this->m.grid->get_start( &dx, &dy ); - - drag_x = x; - drag_y = y; - - take_focus(); - } - else - processed = 0; - - break; - } - case 3: - { - int note; - if ( ( note = is_row_press() ) >= 0 ) - { - /* inside the note headings */ - - DMESSAGE( "click on row %d", note ); - if ( IS_PATTERN ) - { - Instrument *i = ((pattern *)c->grid())->mapping.instrument(); - - if ( i ) - { - ui->edit_instrument_row( i, note ); - - c->changed_mapping(); - } - } - } - else - { - _selection_mode = SELECT_RECTANGLE; - { - drag_x = Fl::event_x(); - drag_y = Fl::event_y(); - - _selection_rect.x1 = drag_x; - _selection_rect.y1 = drag_y; - _selection_rect.x2 = drag_x; - _selection_rect.y2 = drag_y; - signal_settings_change(); - return 1; - } - - return 1; - break; - - - } - - /* if ( Fl::event_state() & FL_SHIFT ) */ - /* { */ - /* c->end_cursor( x, y ); */ - /* break; */ - /* } */ - break; - } - default: - processed = 0; - } - break; - } - case FL_RELEASE: - { - _move_mode = false; - - if ( SELECT_RANGE == _selection_mode ) - { - select_range(); - _selection_mode = SELECT_NONE; - return 1; - } - else if ( SELECT_RECTANGLE == _selection_mode ) - { - int X,Y,W,H; - - SelectionRect &s = _selection_rect; - - X = s.x1 < s.x2 ? s.x1 : s.x2; - Y = s.y1 < s.y2 ? s.y1 : s.y2; - W = s.x1 < s.x2 ? s.x2 - s.x1 : s.x1 - s.x2; - H = s.y1 < s.y2 ? s.y2 - s.y1 : s.y1 - s.y2; - - int endx = X + W; - int endy = Y + H; - int beginx = X; - int beginy = Y; - - grid_pos( &beginx, &beginy ); - grid_pos( &endx, &endy ); - - /* if ( is_ruler_click() ) */ - /* { */ - /* grid()->select( beginx, endx ); */ - /* } */ - /* else */ - { - grid()->select( beginx, endx, beginy, endy ); - } - - _selection_mode = SELECT_NONE; - - _selection_rect.x1 = 0; - _selection_rect.y1 = 0; - _selection_rect.x2 = 0; - _selection_rect.y2 = 0; - - damage(FL_DAMAGE_OVERLAY); - signal_settings_change(); - return 1; - } - - int dx = x; - int dy = y; - grid_pos( &dx, &dy ); - - if ( delete_note ) - { -// this->m.grid->del( dx, dy ); - if ( ghost_note ) - { - damage_grid( ghost_note->start, ghost_note->note, ghost_note->duration, 1 ); - - delete ghost_note; - } - ghost_note = 0; - } - else - if ( ghost_note ) - { - this->m.grid->put( this->m.grid->ts_to_x( ghost_note->start ), - ghost_note->note, - ghost_note->duration, - ghost_note->velocity); - - delete_note = false; - - delete ghost_note; - ghost_note = 0; - } - - if ( drag_note ) - delete drag_note; - drag_note = 0; - - grid()->select_none(); - - break; - } - - case FL_DRAG: - - if ( Fl::event_is_click() ) - return 1; - - { - if ( _selection_mode ) - { - grid()->select_none(); - - _selection_rect.x2 = x; - _selection_rect.y2 = y; - - if ( SELECT_RANGE == _selection_mode ) - { - _selection_rect.y2 = 2000; - c->end_cursor( x, y ); - } - - damage(FL_DAMAGE_OVERLAY); - - return 1; - } - - - int dx = x; - int dy = y; - - grid_pos( &dx, &dy ); - - if ( _move_mode ) - { - int odx = drag_x; - int ody = drag_y; - grid_pos( &odx, &ody ); - - if ( last_move_x != dx ) - { - //this->m.grid->move_selected( dx - move_xoffset ); - if ( dx > last_move_x ) - move_selected( RIGHT, dx - last_move_x ); - else - move_selected( LEFT, last_move_x - dx ); - } - - dy = ntr( dy ); - - if ( dy != last_move_y ) - { - if ( dy > last_move_y ) - move_selected( DOWN, dy - last_move_y ); - else - move_selected( UP, last_move_y - dy ); - } - - last_move_y = dy; - last_move_x = dx; - return 1; - } - - if ( ghost_note ) - { - damage_grid( ghost_note->start, ghost_note->note, ghost_note->duration, 1 ); - - int ody = drag_y; - int odx = drag_x; - - if ( drag_note ) - { - grid_pos( &odx, &ody ); - - /* cursor must leave the row to begin adjusting velocity. */ - if ( ody != dy ) - { - ghost_note->velocity = - drag_note->velocity + - ( (drag_y - y) / 3.0f ); - - if ( ghost_note->velocity < 0 ) - ghost_note->velocity = 0; - else if ( ghost_note->velocity > 127 ) - ghost_note->velocity = 127; - } - } - - if ( dx != odx ) - { - if ( dx > this->m.grid->ts_to_x( ghost_note->start ) ) - { - ghost_note->duration = this->m.grid->x_to_ts( dx ) - ghost_note->start; - } - } - - - damage_grid( ghost_note->start, ghost_note->note, ghost_note->duration, 1 ); - - delete_note = false; - - processed = 2; - - } - } - break; - default: - processed = 0; - } - - if ( processed ) - window()->damage(FL_DAMAGE_OVERLAY); - - if ( processed == 1 ) - damage(FL_DAMAGE_USER1); - - if ( ! processed ) - return Fl_Group::handle( m ); - - return processed; -} diff --git a/sequencer/src/canvas.H b/sequencer/src/canvas.H deleted file mode 100644 index b715f17..0000000 --- a/sequencer/src/canvas.H +++ /dev/null @@ -1,201 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "grid.H" -#include - -#include -using namespace sigc; - -class Mapping; - -enum { LEFT, RIGHT, UP, DOWN, TO_PLAYHEAD, TO_NEXT_NOTE, TO_PREV_NOTE }; - -class Fl_Scrollbar; -class Fl_Slider; - -class Canvas : public Fl_Group, public trackable -{ - class Canvas_Panzoomer; - - struct SelectionRect { - int x1,y1,x2,y2; - }; - - SelectionRect _selection_rect; - - int _selection_mode; - bool _move_mode; - Canvas_Panzoomer *panzoomer; - Fl_Slider *vzoom; - - /* these are grid coords, not pixels */ - int _old_scroll_x; - int _old_scroll_y; - - struct { - int origin_x, origin_y; - int width, height; - - int margin_left, margin_top; - int div_w, div_h; - - int old_div_w, old_div_h; - - int maxh; - - bool ruler_drawn; - bool mapping_drawn; - - bool grid_drawn; - - int playhead; /* where the playhead is for this canvas. only used for display. */ - - enum { PATTERN, SEQUENCE } mode; - - Grid *grid; /* grid currently connected to this canvas */ - - size_t size; - - bool draw; /* really drawing, or just checking size? */ - - int rule; - - bool row_compact; /* use row-compaction? */ - - /* tables used for row-compaction */ - int rtn[128]; /* row-to-note */ - int ntr[128]; /* note-to-row */ - - Viewport *vp; - int w, h; - - uint p1, p2; /* range cursors */ - uint p3, p4; /* row cursors */ - } m; - - bool is_ruler_click ( void ) const; - int rtn ( int r ) const; - int ntr ( int n ) const; - - void _update_row_mapping ( void ); - - void draw_mapping ( void ); - void draw_ruler ( void ); - - void _reset ( void ); - void _lr ( void ); - - bool viewable_x ( int x ); - - void update_mapping ( void ); - - static void cb_scroll ( Fl_Widget *w, void *v ); - void cb_scroll ( Fl_Widget *w ); - static void draw_clip ( void *v, int X, int Y, int W, int H ); - void draw_clip ( int X, int Y, int W, int H ); - -enum { - SELECT_NONE = 0, - SELECT_RECTANGLE, - SELECT_RANGE -}; - -public: - - bool selection_mode ( void ) const { return _selection_mode; } - void selection_mode ( bool b ) - { - _selection_mode = b ? SELECT_RECTANGLE : SELECT_NONE; - } - - enum { OFF, ON, TOGGLE }; - - signal signal_settings_change; - - Canvas ( int X, int Y, int W, int H, const char *L=0 ); - virtual ~Canvas ( ); - - void cut ( void ); - void paste ( void ); - void redraw_playhead ( void ); - void handle_event_change ( void ); - void set ( int x, int y ); - void grid ( Grid *g ); - void changed_mapping ( void ); - Grid * grid ( void ); - void adj_size ( void ); - void resize_grid ( void ); - void resize ( int x, int y, int w, int h ); - void copy ( void ); - void draw_row_name ( int y, const char *name, int color ); - // void draw_shape ( int x, int y, int w, int color ); - static void draw_dash ( tick_t x, int y, tick_t l, int color, int selected, void *userdata ); - void draw_dash ( tick_t x, int y, tick_t w, int color, int selected ) const; - void damage_grid ( tick_t x, int y, tick_t w, int h ); - void draw_overlay ( void ); - void draw_playhead ( void ); - void draw ( void ); - bool grid_pos ( int *x, int *y ) const; - int is_row_press ( void ) const; - void unset ( int x, int y ); - void adj_color ( int x, int y, int n ); - void adj_length ( int x, int y, int n ); - void set_end ( int x, int y, int n ); - void select ( int x, int y ); - void select_range ( void ); - void invert_selection ( void ); - void duplicate_range ( void ); - void crop ( void ); - void row_compact ( int n ); - void pan ( int dir, int n ); - void can_scroll ( int *left, int *right, int *up, int *down ); - void h_zoom ( float n ); - void v_zoom ( float n ); - void v_zoom_fit ( void ); - void notes ( char *s ); - char * notes ( void ); - int playhead_moved ( void ); - - void start_cursor ( int x, int y ); - void end_cursor ( int x, int y ); - - void delete_time ( void ); - void insert_time ( void ); - - void move_selected ( int dir, int n ); - void selected_velocity ( int v ); - - virtual int handle ( int m ); - -}; - -inline int -Canvas::rtn ( int r ) const -{ - return m.row_compact ? m.rtn[ r ] : r; -} - -inline int -Canvas::ntr ( int n ) const -{ - return m.row_compact ? m.ntr[ n ] : n; -} diff --git a/sequencer/src/common.h b/sequencer/src/common.h deleted file mode 100644 index 7c179a8..0000000 --- a/sequencer/src/common.h +++ /dev/null @@ -1,38 +0,0 @@ - - -/*******************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -// #pragma once - -typedef unsigned char byte_t; -typedef double tick_t; -typedef unsigned int uint; - - -/* #define min(x,y) ((x) < (y) ? (x) : (y)) */ -/* #define max(x,y) ((x) > (y) ? (x) : (y)) */ - -#include -using namespace std; - -#define elementsof(x) (sizeof((x)) / sizeof((x)[0])) - -#include "config.h" -#include "const.h" -#include "debug.h" diff --git a/sequencer/src/config.h b/sequencer/src/config.h deleted file mode 100644 index 853ca18..0000000 --- a/sequencer/src/config.h +++ /dev/null @@ -1,3 +0,0 @@ - - -// #define INSTALL_PREFIX "/usr/local/" diff --git a/sequencer/src/const.h b/sequencer/src/const.h deleted file mode 100644 index 0eeb0d6..0000000 --- a/sequencer/src/const.h +++ /dev/null @@ -1,41 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -/* getting around this will require bank switching etc, and - before that happens I'd like to see a song with 128 phrases in it. */ -const int MAX_PHRASE = 128; -const int MAX_PATTERN = 128; - -const unsigned int PPQN = 480; - -/* interval between GUI updates for playhead movement, etc. */ -const double TRANSPORT_POLL_INTERVAL = 0.02; - -const char APP_NAME[] = "Non-Sequencer"; -const char APP_TITLE[] = "The Non-Sequencer"; -const char COPYRIGHT[] = "Copyright (c) 2007-2013 Jonathan Moore Liles"; - -#define PACKAGE "non-sequencer" - -/* directories */ - -#define USER_CONFIG_DIR ".non/" -#define INSTRUMENT_DIR "instruments/" diff --git a/sequencer/src/debug.C b/sequencer/src/debug.C deleted file mode 100644 index 47e46fe..0000000 --- a/sequencer/src/debug.C +++ /dev/null @@ -1,62 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "debug.h" - -void -warnf ( warning_t level, - const char *module, - const char *file, - const char *function, size_t line, const char *fmt, ... ) -{ - va_list args; - static const char *level_tab[] = { - "message", "\033[1;32m", - "warning", "\033[1;33m", - "assertion", "\033[1;31m" - }; - - FILE *fp = W_MESSAGE == level ? stdout : stderr; - - if ( module ) - fprintf( fp, "[%s] ", module ); -#ifndef NDEBUG - if ( file ) - fprintf( fp, "%s", file ); - if ( line ) - fprintf( fp, ":%lu", line ); - if ( function ) - fprintf( fp, " %s()", function ); - - fprintf( fp, ": " ); -#endif - - if ( unsigned( ( level << 1 ) + 1 ) < - ( sizeof( level_tab ) / sizeof( level_tab[0] ) ) ) - fprintf( fp, "%s", level_tab[( level << 1 ) + 1] ); - - if ( fmt ) - { - va_start( args, fmt ); - vfprintf( fp, fmt, args ); - va_end( args ); - } - - fprintf( fp, "\033[0m\n" ); -} diff --git a/sequencer/src/debug.h b/sequencer/src/debug.h deleted file mode 100644 index 126d6fc..0000000 --- a/sequencer/src/debug.h +++ /dev/null @@ -1,116 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* debug.h - * - * 11/21/2003 - Jonathan Moore Liles - * - * Debuging support. - * - * Disable by defining the preprocessor variable NDEBUG prior to inclusion. - * - * The following macros sould be defined as string literals - * - * name value - * - * __MODULE__ Name of module. eg. "libfoo" - * - * __FILE__ Name of file. eg. "foo.c" - * - * __FUNCTION__ Name of enclosing function. eg. "bar" - * - * (inteter literal) - * __LINE__ Number of enclosing line. - * - * - * __FILE__, and __LINE__ are automatically defined by standard CPP - * implementations. __FUNCTION__ is more or less unique to GNU, and isn't - * strictly a preprocessor macro, but rather a reserved word in the compiler. - * There is a sed script available with this toolset that is able to fake - * __FUNCTION__ (among other things) with an extra preprocesessing step. - * - * __MODULE__ is nonstandard and should be defined the enclosing program(s). - * Autoconf defines PACKAGE as the module name, and these routines will use its - * value instead if __MODULE__ is undefined. - * - * The following routines are provided (as macros) and take the same arguments - * as printf(): - * - * MESSAGE( const char *format, ... ) - * WARNING( const char *format, ... ) - * ASSERTION( const char *format, ... ) - * - * Calling MESSAGE or WARNING prints the message to stderr along with module, - * file and line information, as well as appropriate emphasis. Calling - * ASSERTION will do the same, and then call abort() to end the program. It is - * unwise to supply any of these marcros with arguments that produce side - * effects. As, doing so will most likely result in Heisenbugs; program - * behavior that changes when debugging is disabled. - * - */ - - -#ifndef _DEBUG_H -#define _DEBUG_H - -#ifndef __MODULE__ -#ifdef PACKAGE -#define __MODULE__ PACKAGE -#else -#define __MODULE__ NULL -#endif -#endif - -#ifndef __GNUC__ - #define __FUNCTION__ NULL -#endif - -#include -#include -#include - -typedef enum { - W_MESSAGE = 0, - W_WARNING, - W_ASSERTION -} warning_t; - -void -warnf ( warning_t level, - const char *module, - const char *file, - const char *function, size_t line, const char *fmt, ... ); - - -#ifndef NDEBUG -#define DMESSAGE( fmt, args... ) warnf( W_MESSAGE, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ) -#define DWARNING( fmt, args... ) warnf( W_WARNING, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ) -#define ASSERT( pred, fmt, args... ) do { if ( ! (pred) ) { warnf( W_ASSERTION, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ); abort(); } } while ( 0 ) -#else -#define DMESSAGE( fmt, args... ) -#define DWARNING( fmt, args... ) -#define ASSERT( pred, fmt, args... ) -#endif - -/* these are always defined */ -#define MESSAGE( fmt, args... ) warnf( W_MESSAGE, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ) -#define WARNING( fmt, args... ) warnf( W_WARNING, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ) -#define ASSERTION( fmt, args... ) ( warnf( W_ASSERTION, __MODULE__, __FILE__, __FUNCTION__, __LINE__, fmt, ## args ), abort() ) - -#endif diff --git a/sequencer/src/grid.C b/sequencer/src/grid.C deleted file mode 100644 index 121f14b..0000000 --- a/sequencer/src/grid.C +++ /dev/null @@ -1,1024 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "grid.H" -#include "common.h" -#include "canvas.H" - -#include "non.H" - -#include "smf.H" - -using namespace MIDI; - -MIDI::event_list Grid::_clipboard; - -Grid::Grid ( void ) -{ - _name = NULL; - _notes = NULL; - _number = 0; - _height = 0; - - _rd = new data; - _rw = NULL; - - // we need to initialize it here. - data *d = (data *)_rd; - - _mode = 0; - _locked = 0; - - d->length = 0; - - _bpb = 4; - /* how many grid positions there are per beat */ - _ppqn = 4; - - viewport.h = 32; - viewport.w = 32; - viewport.x = 0; - viewport.y = 0; - - _playing = false; - _start = _end = _index = 0; -} - -Grid::~Grid ( void ) -{ - DMESSAGE( "deleting grid" ); - - if ( _name ) - free( _name ); - if ( _notes ) - free( _notes ); - - if ( _rw ) - delete _rw; - if ( _rd ) - delete _rd; - -} - -/* copy constructor */ -Grid::Grid ( const Grid &rhs ) : sigc::trackable() -{ - _rd = new data( *rhs._rd ); - _rw = NULL; - - _name = rhs._name ? strdup( rhs._name ) : NULL; - _notes = rhs._notes ? strdup( rhs._notes ) : NULL; - _number = rhs._number; - _height = rhs._height; - - _mode = 0; - _locked = 0; - _playing = false; - _index = 0; - _start = 0; - _end = 0; - - _bpb = rhs._bpb; - _ppqn = rhs._ppqn; - - viewport = rhs.viewport; -} - -void -Grid::lock ( void ) -{ - if ( ! _locked++ ) - _rw = new data( *_rd ); -} - -void -Grid::unlock ( void ) -{ - if ( 0 == --_locked ) - { - _history.push_back( const_cast( _rd ) ); - - if ( _history.size() > MAX_UNDO + 1 ) - { - data *d = _history.front(); - - delete d; - - _history.pop_front(); - } - - // swap the copy back in (atomically). - _rd = (const data *)_rw; - - _rw = NULL; - - signal_events_change(); - } -} - -event * -Grid::_event ( int x, int y, bool write ) const -{ - const data *d = const_cast< data * >(_rd); - - const event_list *r = write ? &_rw->events : &d->events; - - tick_t xt = x_to_ts(x); - - if ( r->empty() ) -/* || xt > _rd->length ) */ - return NULL; - - int note = y_to_note( y ); - - for ( event *e = r->first(); e; e = e->next() ) - { - if ( ! e->is_note_on() ) - continue; - - if ( e->note() != note ) - continue; - - tick_t ts = e->timestamp(); - tick_t l = 0; - - if ( e->linked() ) - l = e->link()->timestamp() - ts; - else - WARNING( "found unlinked event... event list is corrupt." ); - - if ( xt >= ts && xt < ts + l ) - // this is a little nasty - return const_cast(e); - } - - return NULL; -} - -bool -Grid::_delete ( int x, int y ) -{ - event *e = _event ( x, y, true ); - - if ( e ) - { - if ( e->linked() ) - _rw->events.remove( e->link() ); - - _rw->events.remove( e ); - - return true; - } - - return false; -} - -void -Grid::clear ( void ) -{ - lock(); - - _rw->events.clear(); - - unlock(); -} - -void -Grid::del ( int x, int y ) -{ - lock(); - - _delete( x, y ); - - unlock(); -} - -int -Grid::next_note_x ( int x ) const -{ - for ( const event *e = _rd->events.first(); e; e = e->next() ) - if ( e->is_note_on() && (ts_to_x( e->timestamp() ) > (uint)x ) ) - return ts_to_x( e->timestamp() ); - - return 0; -} - -int -Grid::prev_note_x ( int x ) const -{ - for ( const event *e = _rd->events.last(); e; e = e->prev() ) - if ( e->is_note_on() && (ts_to_x( e->timestamp() ) < (uint)x) ) - return ts_to_x( e->timestamp() ); - - return 0; -} - - -void -Grid::_fix_length ( void ) -{ - tick_t beats = (unsigned long)(_rw->length / PPQN); - tick_t rem = (unsigned long)_rw->length % PPQN; - - _rw->length = (rem ? (beats + 1) : beats) * PPQN; -} - -/** Trim the length of the grid to the last event */ -void -Grid::trim ( void ) -{ - lock(); - - event *e = _rw->events.last(); - - if ( e ) - { - tick_t ts = e->timestamp(); - - _rw->length = ts; - - _fix_length(); - } - - unlock(); -} - -void -Grid::fit ( void ) -{ - int hi, lo; - - _rd->events.hi_lo_note( &hi, &lo ); - - viewport.h = abs( hi - lo ) + 1; - - viewport.y = note_to_y( hi ); -} - -/** Expand the length of the grid to the last event */ -void -Grid::expand ( void ) -{ - lock(); - - event *e = _rw->events.last(); - - if ( e ) - { - tick_t ts = e->timestamp(); - - _rw->length = ts > _rw->length ? ts : _rw->length; - - _fix_length(); - } - - unlock(); -} - -/** returns true if there is a note event at x,y */ -bool -Grid::is_set ( int x, int y ) const -{ - return _event( x, y, false ); -} - -void -Grid::put ( int x, int y, tick_t l, int velocity ) -{ - - int xl = ts_to_x( l ); - tick_t ts = x_to_ts( x ); - - event *on = new event; - event *off = new event; - - // Don't allow overlap (Why not?) - if ( _event( x, y, false ) || - _event( x + xl, y, false ) ) - return; - - DMESSAGE( "put %d,%d", x, y ); - - lock(); - - int note = y_to_note( y ); - - on->status( event::NOTE_ON ); - on->note( note ); - on->timestamp( ts ); - on->note_velocity( velocity ); - on->link( off ); - - off->status( event::NOTE_OFF ); - off->note( note ); - off->timestamp( ts + l ); - off->note_velocity( velocity ); - off->link( on ); - - _rw->events.insert( on ); - _rw->events.insert( off ); - - - expand(); - - unlock(); -} - - -// void -// pattern::move ( int x, int y, int nx ) -// { -// event *e = _event( x, y, false ); - -// if ( e ) -// e->timestamp( nx ); -// } - - -void -Grid::move ( int x, int y, int nx, int ny ) -{ - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - DMESSAGE( "moving note" ); - - event *on = e, - *off = e->link(); - - _rw->events.unlink( on ); - _rw->events.unlink( off ); - - on->note( y_to_note( ny ) ); - - tick_t l = on->note_duration(); - on->timestamp( x_to_ts( ny ) ); - on->note_duration( l ); - - _rw->events.insert( off ); - _rw->events.insert( on ); - } - - unlock(); -} - - -void -Grid::adj_velocity ( int x, int y, int n ) -{ - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - DMESSAGE( "adjusting velocity" ); - - { - int v = e->note_velocity(); - - v += n; - - if ( v > 127 ) - v = 127; - - e->note_velocity( v > 0 ? v : 1 ); - } - - } - - unlock(); - -} - -void -Grid::adj_duration ( int x, int y, int l ) -{ - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - DMESSAGE( "adjusting duration" ); - - { - int v = ts_to_x( e->note_duration() ); - - v += l; - - e->note_duration( x_to_ts( v > 0 ? v : 1 ) ); - - _rw->events.sort( e->link() ); - } - - } - - unlock(); - -} - -void -Grid::set_duration ( int x, int y, int ex ) -{ - if ( ex < 1 ) - return; - - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - DMESSAGE( "adjusting duration" ); - - e->note_duration( x_to_ts( ex ) ); - - _rw->events.sort( e->link() ); - } - - unlock(); -} - -void -Grid::get_note_properties ( int x, int y, note_properties *p ) const -{ - const event *e = _event( x, y, false ); - - e->get_note_properties( p ); - - p->start = p->start; - p->duration = p->duration; - p->note = note_to_y( p->note ); -} - -/* void */ -/* Grid::set_note_properties ( int x, int y, const note_properties *p ) */ -/* { */ -/* lock(); */ - -/* const event *e = _event( x, y, true ); */ - -/* e->set_note_properties( p ); */ - -/* unlock(); */ -/* } */ - - - - -/** if there's a note at grid coordinates x,y, then adjust them to the beginning of the note */ -int -Grid::get_start ( int *x, int *y ) const -{ - const event *e = _event( *x, *y, false ); - - if ( e ) - { - *x = ts_to_x( e->timestamp() ); - return 1; - } - else - return 0; -} - -void -Grid::set_end ( int x, int y, int ex ) -{ - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - DMESSAGE( "adjusting duration" ); - - tick_t ts = x_to_ts( ex ); - - if ( ts > e->timestamp() && - ts - e->timestamp() > x_to_ts( 1 ) ) - { - e->note_duration( ts - e->timestamp() ); - - _rw->events.sort( e->link() ); - } - } - - unlock(); -} - -void -Grid::toggle_select ( int x, int y ) -{ - lock(); - - event *e = _event( x, y, true ); - - if ( e ) - { - if ( e->selected() ) - e->deselect(); - else - e->select(); - } - - unlock(); -} - -/** copy selected notes to clipboard */ -void -Grid::copy ( void ) -{ - _rd->events.copy_selected( &_clipboard ); -} - -void -Grid::cut ( void ) -{ - _rd->events.copy_selected( &_clipboard ); - - lock(); - - _rw->events.remove_selected(); - - unlock(); -} - -void -Grid::selected_velocity ( int v ) -{ - lock(); - - _rw->events.selected_velocity( v ); - - unlock(); -} - -void -Grid::paste ( int offset ) -{ - lock(); - - _rw->events.paste( x_to_ts( offset ), &_clipboard ); - - expand(); - - unlock(); - -} - -/** insert /l/ ticks of time after /x/ */ -void -Grid::insert_time ( int l, int r ) -{ - tick_t start = x_to_ts( l ); - tick_t end = x_to_ts( r ); - - lock(); - - _rw->events.insert_time( start, end - start ); - - expand(); - - unlock(); -} - -/** select all events in range (notes straddling the border will also be selected */ -void -Grid::select ( int l, int r ) -{ - tick_t start = x_to_ts( l ); - tick_t end = x_to_ts( r ); - - lock(); - - _rw->events.select( start, end ); - - unlock(); -} - -/** select all (note) events in rectangle */ -void -Grid::select ( int l, int r, int t, int b ) -{ - tick_t start = x_to_ts( l ); - tick_t end = x_to_ts( r ); - - lock(); - - _rw->events.select( start, end, y_to_note( t) , y_to_note( b ) ); - - unlock(); -} - -/** delete events from /x/ to /l/, compressing time. */ -void -Grid::delete_time ( int l, int r ) -{ - tick_t start = x_to_ts( l ); - tick_t end = x_to_ts( r ); - - lock(); - - _rw->events.delete_time( start, end ); - - unlock(); -} - -void -Grid::select_none ( void ) -{ - lock(); - - _rw->events.select_none(); - - unlock(); -} - -void -Grid::select_all ( void ) -{ - lock(); - - _rw->events.select_all(); - - unlock(); -} - -void -Grid::invert_selection ( void ) -{ - lock(); - - _rw->events.invert_selection(); - - unlock(); -} - -void -Grid::delete_selected ( void ) -{ - lock(); - - _rw->events.remove_selected(); - - unlock(); -} - -void -Grid::nudge_selected ( int l ) -{ - long o = x_to_ts( abs( l ) ); - - if ( l < 0 ) - o = 0 - o; - - lock(); - -// MESSAGE( "moving by %ld", o ); - - _rw->events.nudge_selected( o ); - - unlock(); -} - -void -Grid::move_selected ( int l ) -{ - tick_t o = x_to_ts( l ); - - lock(); - -// MESSAGE( "moving by %ld", o ); - - _rw->events.move_selected( o ); - - unlock(); -} - -void -Grid::crop ( int l, int r ) -{ - lock(); - - if ( (uint)r < ts_to_x( _rw->length ) ) - delete_time( r, ts_to_x( _rw->length ) ); - if ( l > 0 ) - delete_time( 0, l ); - - trim(); - - unlock(); -} - -void -Grid::crop ( int l, int r, int t, int b ) -{ - lock(); - - _rw->events.push_selection(); - - select( l, r, t, b ); - - _rw->events.invert_selection(); - _rw->events.remove_selected(); - - _rw->events.pop_selection(); - - crop( l, r ); - - unlock(); -} - -int -Grid::min_selected ( void ) const -{ - return ts_to_x( _rd->events.selection_min() ); -} - -void -Grid::_relink ( void ) -{ - _rw->events.relink(); -} - -/* Dump the event list -- used by pattern / phrase dumppers */ -void -Grid::dump ( smf *f, int channel ) const -{ - data *d = const_cast(_rd); - - midievent me; - - for ( event *e = d->events.first(); e; e = e->next() ) - { - me = *e; - me.channel( channel ); - - f->write_event( &me ); - } -} - -void -Grid::print ( void ) const -{ - data *d = const_cast(_rd); - - for ( event *e = d->events.first(); e; e = e->next() ) - e->print(); -} - - -/* */ - -/** Invoke /draw_note/ function for every note in the viewport */ -void -Grid::draw_notes ( draw_note_func_t draw_note, void *userdata ) const -{ - data *d = const_cast< data *>( _rd ); - - for ( const event *e = d->events.first(); e; e = e->next() ) - { - if ( ! e->is_note_on() ) - continue; - - const tick_t ts = e->timestamp(); - - ASSERT( e->link(), "found a non-linked note" ); - - const tick_t tse = e->link()->timestamp(); - - draw_note( - ts, - note_to_y( e->note() ), - tse - ts, - e->note_velocity(), - e->selected(), - userdata ); - } -} - - /*******************************************/ - /* Generic accessors -- boy C++ is verbose */ - /*******************************************/ - -/** Returns the index (playhead) for this grid */ -tick_t -Grid::index ( void ) const -{ - /* FIXME: considering the type of tick_t, we really need some kind - of locking here to insure that this thread doesn't read _index - while the RT thread is writing it. */ - return _index; -} - -bool -Grid::playing ( void ) const -{ - return _playing; -} - -int -Grid::height ( void ) const -{ - return _height; -} - -void -Grid::height ( int h ) -{ - _height = h; -} - -tick_t -Grid::length ( void ) const -{ - return _rd->length; -} - -void -Grid::length ( tick_t l ) -{ - lock(); - - _rw->length = l; - - unlock(); -} - -void -Grid::bars ( int n ) -{ - lock(); - - _rw->length = n * _bpb * PPQN; - - _fix_length(); - - unlock(); - - // trim(); - - signal_events_change(); -} - -int -Grid::bars ( void ) const -{ - return beats() / _bpb; -} - -int -Grid::beats ( void ) const -{ - return _rd->length / PPQN; -} - -int -Grid::division ( void ) const -{ - return _bpb * _ppqn; -} - -int -Grid::subdivision ( void ) const -{ - return _ppqn; -} - -int -Grid::ppqn ( void ) const -{ - return _ppqn; -} - -/** set grid resolution to /n/, where /n/ is the denominator e.g. 1/n. */ -void -Grid::resolution ( unsigned int n ) -{ - float W = viewport.w / _ppqn; - - _ppqn = n; - - viewport.w = _ppqn * W; - - signal_events_change(); - - signal_settings_change(); -} - -int -Grid::resolution ( void ) const -{ - return _ppqn; -} - -int -Grid::number ( void ) const -{ - return _number; -} - -void -Grid::name ( char *s ) -{ - if ( _name ) free ( _name ); - - _name = s; - - signal_settings_change(); -} - -const char * -Grid::name ( void ) const -{ - return _name; -} - -void -Grid::notes ( char *s ) -{ - if ( _notes ) free ( _notes ); - - _notes = s; - - signal_settings_change(); -} - -char * -Grid::notes ( void ) const -{ - return _notes; -} - -void -Grid::mode ( int m ) -{ - _mode = m; - - /* can't do this in RT thread, sorry. */ -/// signal_settings_change(); -} - -int -Grid::mode ( void ) const -{ - return _mode; -} - -void -Grid::undo ( void ) -{ - if ( ! _history.size() ) - return; - - data *d = _history.back(); - - _history.pop_back(); - - // swap the copy back in (atomically). - _rd = (const data *)d; - - _rw = NULL; - - signal_events_change(); -} - -/** return a pointer to a copy of grid's event list in raw form */ -event_list * -Grid::events ( void ) const -{ - data * d = const_cast< data * >( _rd ); - - return new event_list( d->events ); -} - -/** replace event list with a copy of /el/ */ -void -Grid::events ( const event_list * el ) -{ - lock(); - - _rw->events = *el; - - unlock(); -} diff --git a/sequencer/src/grid.H b/sequencer/src/grid.H deleted file mode 100644 index ca39d43..0000000 --- a/sequencer/src/grid.H +++ /dev/null @@ -1,282 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include -#include "const.h" -#include "instrument.H" - -class smf; - -#include "debug.h" - -const int MAX_UNDO = 50; - -#include - -#include -using namespace sigc; - -using std::list; - -/* patterns and phrases use this structure */ - -class Canvas; - -/* everything that must be lock-free. This whole structure gets copied and swapped - for each write method */ -struct data { - - tick_t length; - int state; - MIDI::event_list events; - - data( void ) - { - length = 0; - state = 0; - } - - data( const data &rhs ) - { - events = rhs.events; - length = rhs.length; - state = rhs.state; - } -/* data() { MESSAGE( "allocating new editable data" ); } */ - // ~data() { MESSAGE( "deleting old undo data, freeing at least %d bytes.", events.size() * sizeof ( event ) + sizeof ( list )); } -}; - - -struct Viewport { - - #define format "%d:%d:%d:%d" - - int x, y, w, h; - - Viewport ( void ) - { - x = y = w = h = 0; - } - - char * - dump ( void ) const - { - char *s; - - asprintf( &s, format, x, y, w, h ); - - return s; - } - - void - read( const char *s ) - { - sscanf( s, format, &x, &y, &w, &h ); - } - - #undef format -}; - - - -class Grid : public trackable -{ - static MIDI::event_list _clipboard; - -protected: - - unsigned int _height; - char *_notes; - char *_name; - int _number; - - unsigned int _bpb; /* beats per bar */ - unsigned int _ppqn; /* pulses per quarter note (beat) */ - - - /* Used by playback thread. When a pattern or phrase is triggered, - these fields are filled in appropriately */ - mutable tick_t _start; /* absolute start tick of loop */ - mutable tick_t _end; /* absolute end tick of loop */ - volatile mutable tick_t _index; /* playhead, relative to start -- primarily used to draw the playhead */ - volatile mutable bool _playing; /* true if currently playing */ - - mutable volatile int _mode; /* mute, solo */ - - // FIXME: shouldn't this be "volatile"? -// const volatile data *_rd; /* read only data used by RT thread */ - const data * volatile _rd; - data *_rw; /* temporary writable copy used by UI thread */ - - list _history; - - void _remove_marked ( void ); - MIDI::event * _event ( int x, int y, bool write ) const; - bool _delete ( int x, int y ); - void _link ( void ); - void _relink ( void ); - void _fix_length ( void ); - - -private: - - volatile int _locked; - -public: - - typedef void draw_note_func_t ( tick_t x, int y, tick_t l, int velocity, int selected, void *userdata ); - - void draw_notes ( draw_note_func_t draw_note, void *userdata ) const; - - signal signal_events_change; - signal signal_settings_change; - - Viewport viewport; /* used by the Canvas */ - - Grid ( void ); - virtual ~Grid ( void ); - Grid ( const Grid &rhs ); - - virtual bool velocity_sensitive ( void ) const { return true; } - - int y_to_note ( int y ) const; - int note_to_y ( int n ) const; - tick_t x_to_ts ( unsigned long x ) const; - double ts_to_x ( tick_t ts ) const; - - virtual Grid * create ( void ) = 0; - virtual Grid * clone ( void ) = 0; - virtual void draw_row_names ( Canvas *c ) const = 0; - virtual const char * row_name ( int r ) const = 0; - - virtual Grid * by_number ( int n ) const = 0; - - virtual void put ( int x, int y, tick_t l, int velocity = 64 ); - virtual bool is_set ( int x, int y ) const; - - void lock ( void ); - void unlock ( void ); - void clear ( void ); - void del ( int x, int y ); - void adj_velocity ( int x, int y, int n ); - void adj_duration ( int x, int y, int l ); - void set_duration ( int x, int y, int l ); - void set_end ( int x, int y, int l ); - int get_start ( int *x, int *y ) const; - void move ( int x, int y, int nx, int ny ); - void record_event ( MIDI::event *e ); - tick_t index ( void ) const; - bool playing ( void ) const; - - int height ( void ) const; - void height ( int h ); - tick_t length ( void ) const; - void length ( tick_t l ); - - void bars ( int n ); - int bars ( void ) const; - int beats ( void ) const; - void trim ( void ); - void expand ( void ); - int division ( void ) const; - int subdivision ( void ) const; - int ppqn ( void ) const; - int number ( void ) const; - void name ( char *s ); - const char * name ( void ) const; - void notes ( char *s ); - char * notes ( void ) const; - virtual void mode ( int m ); - virtual int mode ( void ) const; - int next_note_x ( int x ) const; - int prev_note_x ( int x ) const; - - void fit ( void ); - - void delete_selected ( void ); - void move_selected ( int l ); - void nudge_selected ( int l ); - void selected_velocity ( int v ); - - void crop ( int l, int r ); - void crop ( int l, int r, int t, int b ); - - void toggle_select ( int x, int y ); - void insert_time ( int x, int r ); - void select ( int start, int end ); - void select ( int start, int end, int t, int b ); - void delete_time ( int start, int end ); - void select_none ( void ); - void select_all ( void ); - void invert_selection ( void ); - - void resolution ( unsigned int n ); - int resolution ( void ) const; - - void dump ( smf *f, int channel ) const; - void draw ( Canvas *c, int bx, int by, int bw, int bh ); - void print ( void ) const; - - MIDI::event_list * events ( void ) const; - void events ( const MIDI::event_list * el ); - - void get_note_properties ( int x, int y, MIDI::note_properties *p ) const; - - int min_selected ( void ) const; - - void cut ( void ); - void copy ( void ); - void paste ( int offset ); - - void undo ( void ); - - virtual tick_t default_length ( void ) const - { - return PPQN; - } - -}; - - -inline int -Grid::y_to_note ( int y ) const -{ - return 127 - y; -} - -inline int -Grid::note_to_y ( int n ) const -{ - return 127 - n; -} - -inline tick_t -Grid::x_to_ts ( unsigned long x ) const -{ - return (x * PPQN) / _ppqn; -} - -inline double -Grid::ts_to_x ( tick_t ts ) const -{ - return (ts * _ppqn) / PPQN; -} diff --git a/sequencer/src/gui/event_edit.fl b/sequencer/src/gui/event_edit.fl deleted file mode 100644 index d4c924b..0000000 --- a/sequencer/src/gui/event_edit.fl +++ /dev/null @@ -1,546 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -comment {// -// Copyright (C) 2008 Jonathan Moore Liles -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -} {in_source in_header -} - -decl {\#include "../grid.H"} {private local -} - -decl {\#include "../scale.H"} {private local -} - -decl {\#include } {public global -} - -decl {\#include } {selected public global -} - -decl {using namespace MIDI;} {private local -} - -decl {extern Fl_Color velocity_colors[];} {private local -} - -decl {class Event_Widget;} {public local -} - -class Event_Editor {open -} { - decl {int _h;} {private local - } - decl {Grid *_grid;} {private local - } - decl {MIDI::event_list *_old;} {private local - } - decl {MIDI::event_list *_el;} {private local - } - decl {int _y;} {private local - } - Function {make_window( Grid *g )} {open - } { - Fl_Window window { - label {Event Editor} - callback {delete _el; - -_grid->events( _old ); - -delete _old; - -_el = _old = NULL; - -o->hide(); - -Fl::delete_widget( o );} open - xywh {968 122 655 805} type Double resizable - code0 {\#include "event_edit.H"} - code1 {\#include "../grid.H"} modal size_range {0 0 659 803} visible - } { - Fl_Scroll {} { - label {Event List} open - xywh {10 29 635 737} type VERTICAL_ALWAYS box FLAT_BOX - } { - Fl_Pack pack {open - xywh {10 29 635 737} color 47 when 6 resizable - } {} - } - Fl_Return_Button {} { - label {&Save} - callback {delete window; -delete _el; -delete _old;} - xywh {489 771 76 25} - } - Fl_Button {} { - label {&Discard} - callback {window->do_callback();} - xywh {575 771 74 25} - } - Fl_Button {} { - label Del - user_data this user_data_type {Event_Editor *} - callback {_el->remove_selected(); - -sync();} - xywh {10 771 74 25} shortcut 0xffff color 88 - } - Fl_Menu_Button {} { - label {&Insert} - user_data this user_data_type {Event_Editor *} - callback {if ( o->value() == 0 ) -{ - // note; - - event *on = new event; - event *off = new event; - - on->status( event::NOTE_ON ); - on->note( 64 ); - on->note_velocity( 64 ); - - off->status( event::NOTE_OFF ); - off->note( 64 ); - off->timestamp( 1 ); - off->note_velocity( 64 ); - - on->link( off ); - - _el->insert( on ); - _el->insert( off ); - -} -else -{ - event *e = new event; - - int opcode = e->name( o->menu()[ o->value() ].text ); - - if ( opcode < 0 ) - return; - - e->status( opcode ); - - Event_Widget *ew = v->value(); - - if ( ew && ew->ev() ) - e->timestamp( ew->ev()->timestamp() ); - - - _el->insert( e ); -} - -sync();} open - xywh {94 771 121 25} color 63 - } { - MenuItem {} { - label Note - xywh {10 10 40 25} - } - MenuItem {} { - label Aftertouch - xywh {50 50 40 25} - } - MenuItem {} { - label {Control Change} - xywh {20 20 40 25} - } - MenuItem {} { - label {Program Change} - xywh {30 30 40 25} - } - MenuItem {} { - label {Channel Pressure} - xywh {60 60 40 25} - } - MenuItem {} { - label {Pitch Wheel} - xywh {40 40 40 25} - } - } - } - code {// keep a copy -_old = g->events(); -_el = g->events(); - -_grid = g; -_y = 0; - -_h = pack->h() / 24; - -update_widgets();} {} - } - Function {sync( void )} {open return_type void - } { - code {DMESSAGE( "syncing events to grid" ); - -_grid->events( _el ); - -update_widgets();} {} - } - Function {update_widgets( void )} {open return_type void - } { - code {int i = 0; -if ( ! _el->empty() ) - -for ( event* e = (*_el)[0]; e; ( e = e->next() ), i++ ) -{ - Event_Widget *ew; - - if ( i < pack->children() ) - { - ew = (Event_Widget*)pack->child(i); - } - else - { - - ew = new Event_Widget( 0, 0, pack->w() - Fl::box_dw( pack->box() ), 24, 0 ); - - ew->callback( cb_changed, (void*)this ); - ew->when( FL_WHEN_CHANGED ); - pack->add( ew ); - } - - ew->ev( e ); -} - -// pack->parent()->redraw();} {} - } - Function {value( void )} {return_type {Event_Widget *} - } { - code {for ( int i = 0; i < pack->children(); i++ ) -{ - Event_Widget *w = (Event_Widget*)pack->child( i ); - if ( w->selected() ) - return w; -} - -return NULL;} {} - } - Function {cb_changed( Fl_Widget *w, void *ee )} {open return_type {static void} - } { - code {Event_Widget *ew = (Event_Widget*)w; - -if ( ew->changed() ) - // sorting order changed. - ((Event_Editor*)ee)->_el->sort( ew->ev() ); - -((Event_Editor*)ee)->sync();} {} - } -} - -Function {event_editor( Grid *g )} {open C return_type void -} { - code {Event_Editor ee; - - -Fl_Window *w = ee.make_window( g ); - -w->modal(); -w->show(); - -while( w->shown() ) - Fl::wait();} {} -} - -widget_class Event_Widget {user_data_type {void *} open - xywh {945 239 590 30} type Single - code0 {_event = NULL;} - class Fl_Group size_range {400 24 0 24} visible -} { - decl {static const Fl_Color note_color = FL_BLACK;} {private local - } - decl {static const Fl_Color control_color = FL_BLUE;} {private local - } - decl {static const Fl_Color prog_color = FL_RED;} {private local - } - decl {static const Fl_Color pressure_color = FL_YELLOW;} {private local - } - decl {static const Fl_Color after_color = FL_CYAN;} {private local - } - decl {static const Fl_Color pitch_color = FL_GREEN} {private local - } - decl {MIDI::event *_event;} {private local - } - decl {Fl_Group *tab;} {private local - } - Function {ev( MIDI::event * e )} {open return_type void - } { - code {if ( e && ( _event == NULL ) ) - activate(); -else -if ( ! e ) -{ - _event = NULL; - deactivate(); - return; -} - -activate(); - -_event = e; - -name->label( e->name() ); -time->value( e->timestamp() ); - -// hide all tabs -for ( int i = 2; i < children(); i++ ) - child( i )->hide(); - -Fl_Valuator *d1, *d2; - -d1 = d2 = NULL; - -name->color( FL_BLACK ); -name->value( e->selected() ); - -// display the proper subtype -switch ( e->opcode() ) -{ -\#define TWO d1 = (Fl_Valuator*)tab->child( 0 ); d2 = (Fl_Valuator*)tab->child( 1 ) -\#define ONE d1 = (Fl_Valuator*)tab->child( 0 ); d2 = NULL - - case midievent::NOTE_ON: - case midievent::NOTE_OFF: - tab = note_tab; - name->color( note_color ); - - note_name->label( Scale::chromatic_name( e->note() ) ); - note_name->labelcolor( velocity_colors[ e->note_velocity() ] ); - - TWO; - break; - case midievent::CONTROL_CHANGE: - tab = control_tab; - name->color( control_color ); - - TWO; - break; - case midievent::AFTERTOUCH: - tab = after_tab; - name->color( after_color ); - - TWO; - break; - case midievent::CHANNEL_PRESSURE: - tab = pressure_tab; - name->color( pressure_color ); - - ONE; - break; - case midievent::PROGRAM_CHANGE: - tab = prog_tab; - name->color( prog_color ); - - ONE; - break; - case midievent::PITCH_WHEEL: - tab = pitch_tab; - name->color( pitch_color ); - - ONE; - d1->value( e->pitch() ); - goto pitch; - break; -} - - -byte_t D1, D2; - -e->data( &D1, &D2 ); - -d1->value( D1 ); -if ( d2 ) - d2->value( D2 ); - - -pitch: - -// show the current tab -tab->show(); - -time->redraw(); -name->redraw(); - -// redraw();} {} - } - Function {ev( void )} {open return_type {MIDI::event *} - } { - code {return _event;} {} - } - Fl_Value_Input time { - callback {if ( _event->is_note_off() ) -{ - if ( o->value() < _event->link()->timestamp() ) - { - o->value( _event->timestamp() ); - return; - } -} -else -if ( _event->is_note_on() ) - if ( o->value() > _event->link()->timestamp() ) - { - o->value( _event->timestamp() ); - return; - } - - -_event->timestamp( o->value() ); - -set_changed(); -do_callback();} - xywh {3 0 125 24} labeltype NO_LABEL align 0 when 8 maximum 0 - code1 {o->maximum( (unsigned long)-1 );} - } - Fl_Button name { - label {} user_data_type {void*} - callback {if ( o->value() ) - _event->select(); -else - _event->deselect(); - -do_callback();} - xywh {132 -1 149 25} type Toggle when 1 - } - Fl_Group note_tab {open - xywh {282 -3 324 37} align 16 - } { - Fl_Value_Input {} { - label {Note:} - user_data this - callback cb_note - xywh {359 0 51 24} when 4 maximum 127 step 1 - } - Fl_Value_Slider {} { - label {Velocity:} - user_data this user_data_type {void *} - callback cb_msb - xywh {480 0 110 24} type {Horz Fill} selection_color 80 align 4 when 4 maximum 127 step 1 - } - Fl_Box note_name { - label {A\#} - private xywh {284 1 31 24} labeltype SHADOW_LABEL labelfont 14 labelcolor 135 - } - } - Fl_Group after_tab {open - xywh {317 0 277 25} align 16 hide - } { - Fl_Value_Input {} { - label {Note:} - user_data this - callback cb_note - xywh {359 0 51 24} when 4 maximum 127 step 1 - } - Fl_Value_Slider {} { - label {Pressure:} - user_data this user_data_type {void *} - callback cb_msb - xywh {480 0 110 24} type {Horz Fill} selection_color 80 align 4 when 4 maximum 127 step 1 - } - } - Fl_Group control_tab {open - xywh {358 0 238 34} align 16 hide - } { - Fl_Value_Input {} { - label {Control:} - user_data this - callback cb_lsb - xywh {359 0 51 24} when 4 maximum 127 step 1 - } - Fl_Value_Input {} { - label {Value:} - user_data this - callback cb_msb - xywh {480 0 51 24} when 4 maximum 127 step 1 - } - } - Fl_Group prog_tab {open - xywh {287 0 238 25} align 16 hide - } { - Fl_Value_Input {} { - label {Program:} - user_data this - callback cb_lsb - xywh {359 0 51 24} when 4 maximum 127 step 1 - } - } - Fl_Group pitch_tab {open - xywh {306 0 290 24} align 16 hide - } { - Fl_Slider {} { - label {Pitch:} user_data_type {void *} - callback {_event->pitch( o->value() ); -do_callback();} - xywh {358 0 231 24} type Horizontal align 4 when 4 minimum -8192 maximum 8191 step 1 - } - } - Fl_Group pressure_tab {open - xywh {307 0 291 24} align 16 hide - } { - Fl_Slider {} { - label {Pressure:} - user_data this - callback cb_lsb - xywh {359 0 230 24} type {Horz Fill} align 4 when 4 maximum 127 step 1 - } - } - Function {select( bool b )} {open return_type void - } { - code {/* -_selected = b; - -if ( b ) - name->color( FL_WHITE ); - -redraw(); -*/} {} - } - Function {button()} {open return_type {Fl_Button *} - } { - code {return name;} {} - } - Function {selected( void )} {open return_type bool - } { - code {/* -int n = name->value(); -name->value( 0 ); -return n; -*/ - -return name->value();} {} - } - Function {cb_lsb( Fl_Valuator *o, Event_Widget *w )} {open return_type {static void} - } { - code {w->ev()->lsb( o->value() ); - -w->do_callback();} {} - } - Function {cb_msb( Fl_Valuator *o, Event_Widget *w )} {open return_type {static void} - } { - code {w->ev()->msb( o->value() ); -w->do_callback();} {} - } - Function {cb_note( Fl_Valuator *o, Event_Widget *w )} {open return_type {static void} - } { - code {w->ev()->note( o->value() ); -w->do_callback();} {} - } -} diff --git a/sequencer/src/gui/ui.fl b/sequencer/src/gui/ui.fl deleted file mode 100644 index b46abc9..0000000 --- a/sequencer/src/gui/ui.fl +++ /dev/null @@ -1,2040 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -comment {// -// Copyright (C) 2008 Jonathan Moore Liles -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -} {in_source in_header -} - -decl {\#include } {public local -} - -decl {\#include } {private local -} - -decl {class Fl_Scalepack;} {public local -} - -decl {class Fl_Sometimes_Input;} {public local -} - -decl {\#include } {public global -} - -decl {\#include } {public local -} - -decl {\#include } {private local -} - -decl {\#include } {public global -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include "event_edit.H"} {private local -} - -decl {\#include "../jack.H"} {private local -} - -decl {\#include "../NSM.H"} {private local -} - -decl {extern NSM_Client *nsm;} {private local -} - -decl {\#include "../transport.H"} {private local -} - -decl {extern UI *ui;} {private local -} - -decl {class O_Canvas;} {private local -} - -decl {class Triggers;} {public local -} - -decl {class Instrument_Editor;} {private local -} - -decl {Fl_Color canvas_background_color;} {public local -} - -decl {Fl_Color velocity_colors[128];} {public local -} - -Function {init_colors()} {open private C return_type {static void} -} { - code {unsigned int i; - /* velocity colors */ - - Fl_Color lo = fl_color_average( FL_CYAN, FL_BLACK, 0.10 ); - Fl_Color hi = fl_color_average( FL_CYAN, FL_WHITE, 0.80 ); - - for ( i = 128; i--; ) - { - velocity_colors[i] = fl_color_average( hi, lo, 1.0 * ((float)i / 128) ); - }} {} -} - -widget_class Visual_Metronome {open - xywh {978 1028 100 100} type Double visible -} { - Fl_Slider progress { - private xywh {139 115 1149 23} type Horizontal box FLAT_BOX color 7 selection_color 54 - code0 {o->resize( x(), (y() + h()) - (h() / 3), w(), h() / 3 );} - code1 {o->slider_size( 0.25 );} - code2 {o->slider( FL_FLAT_BOX );} - } - Function {draw(void)} {open protected return_type void - } { - code {if ( damage() & ~FL_DAMAGE_CHILD ) -{ - if ( ! _bpb ) - return; - -int bw = w() / _bpb; - -int b = _bpb; - -if ( b ) -{ - -for ( int i = 0; i < b; ++i ) -{ - if ( i == _beat ) - fl_color( velocity_colors[ i * 127 / _bpb ] ); - else - fl_color( FL_GRAY ); - - int X = x() + ( i * bw ); - int Y = y(); - int W = bw; - int H = h() - 14; - - fl_rectf(X,Y,W,H); - fl_color( fl_darker( fl_color() ) ); - fl_rect( X,Y,W,H); - - char pat[4]; - - snprintf( pat, sizeof(pat), "%d", i + 1 ); - fl_font( FL_HELVETICA_BOLD, 24 ); - fl_draw( pat, X,Y,W,H, FL_ALIGN_CENTER ); - -} -} -} -progress->resize( x(), y() + h() - 14, w(), 14 ); - -if ( damage() & FL_DAMAGE_CHILD ) - update_child( *progress ); -else - draw_child( *progress ); - -// _flip = ! _flip;} {} - } - decl {int _bpb} {private local - } - decl {int _tpb} {private local - } - decl {int _beat} {private local - } - decl {bool _flip} {private local - } - decl {int _tick} {private local - } - Function {bpb( int b )} {open private return_type void - } { - code {if ( b != _bpb ) -{ - _bpb = b; - redraw(); -}} {} - } - Function {tpb( int ticks )} {open private return_type void - } { - code {_tpb = ticks; - -progress->minimum( 0 ); -progress->maximum( ticks );} {} - } - Function {beat( int b )} {open private return_type void - } { - code {if ( b == _beat || b >= _bpb ) - return; - -_flip = ! _flip; - -_beat = b; -redraw();} {} - } - Function {tick( int tick )} {open private return_type void - } { - code {if ( tick == _tick ) - return; - -if ( _beat < 0 ) - return; - -if ( _flip ) -{ - progress->value( _tpb - tick ); -} -else -{ - progress->value( tick ); -} - -_tick = tick;} {} - } - Function {update( void )} {open return_type void - } { - code {if ( transport.beats_per_bar ) { -bpb( transport.beats_per_bar ); -tpb( transport.ticks_per_beat ); -beat( transport.beat - 1 ); -tick( transport.tick - 1 );}} {} - } - code {_bpb = 0; -_tpb = 0; -_beat = 0; -_tick = 0; -_flip = 0;} {} -} - -class Overlay_Callback_Window {: {public Fl_Overlay_Window} -} { - decl {void (*_draw_overlay_callback)(void*);} {private local - } - decl {void *_draw_overlay_userdata;} {private local - } - Function {Overlay_Callback_Window(int X, int Y, int W, int H, const char *L=0) : Fl_Overlay_Window(X,Y,W,H,L)} {open - } { - code {_draw_overlay_callback = 0; -_draw_overlay_userdata = 0;} {} - } - Function {Overlay_Callback_Window(int W, int H, const char *L=0) : Fl_Overlay_Window(W,H,L)} {open - } { - code {_draw_overlay_callback = 0; -_draw_overlay_userdata = 0;} {} - } - Function {draw_overlay()} {open return_type {virtual void} - } { - code {if ( _draw_overlay_callback ) - _draw_overlay_callback( _draw_overlay_userdata );} {} - } - Function {draw_overlay_callback( void(*cb)(void*), void *v)} {open return_type void - } { - code {_draw_overlay_callback = cb; -_draw_overlay_userdata = v;} {} - } -} - -Function {update_transport( void * )} {open return_type void -} { - code {// transport_poll(); - -handle_midi_input(); - - ui->progress_group->do_callback(); - - ui->vmetro_widget->update(); - - ui->triggers_widget->update(); - -Fl::repeat_timeout( TRANSPORT_POLL_INTERVAL, update_transport ); - -static int oldstate = -1; - -if ( transport.rolling != oldstate ) -{ - - ui->play_button->label( transport.rolling ? "@square" : "@>" ); - oldstate = transport.rolling; - - if ( transport.rolling ) - { - ui->menu_new->deactivate(); - ui->menu_open->deactivate(); - } - else - { - ui->menu_new->activate(); - ui->menu_open->activate(); - } - -} - -if ( nsm && nsm->is_active() ) -{ - if ( ui->menu_new->active() ) - { - ui->menu_new->deactivate(); - ui->menu_open->deactivate(); - ui->menu_save_as->deactivate(); - } -} - -// JUST A TEST -if ( transport.rolling ) -{ - if ( ui->tabs->value() == ui->pattern_tab ) - ui->pattern_canvas_widget->redraw_playhead(); - else - if ( ui->tabs->value() == ui->phrase_tab ) - ui->phrase_canvas_widget->redraw_playhead(); - -} - -ui->transport_state->do_callback();} {} -} - -class UI {open -} { - decl {Fl_Text_Buffer *sequence_notes_buffer;} {private local - } - decl {Fl_Text_Buffer *pattern_notes_buffer;} {private local - } - decl {Fl_Text_Buffer *phrase_notes_buffer} {private local - } - Function {UI()} {open - } { - code {fl_register_images(); - -canvas_background_color = FL_GREEN; - -playback_mode_menu = NULL; - -main_window = make_main_window(); -seq_window = make_seq_window(); - -init_colors(); - -// make_instrument_edit_dialog(); - -// use old focus behavior -Fl::visible_focus( 0 ); - -// try to fill the screen, but only when the screen is tiny and our window is huge. -{ - int sx, sy, sw, sh; - - Fl::screen_xywh( sx, sy, sw, sh ); - - if ( sw < main_window->w() || sh < main_window->h() ) - main_window->resize( sx, sy, sw, sh ); -} - -Fl::add_timeout( TRANSPORT_POLL_INTERVAL, update_transport ); - - -playlist->signal_new_song.connect( sigc::mem_fun( this, &UI::update_sequence_widgets ) ); -pattern_canvas_widget->signal_settings_change.connect( sigc::mem_fun( this, &UI::update_pattern_widgets ) ); -phrase_canvas_widget->signal_settings_change.connect( sigc::mem_fun( this, &UI::update_phrase_widgets ) );} {} - } - Function {~UI()} {open - } { - code {delete seq_window; -delete main_window;} {} - } - Function {run()} {open - } { - code {Fl::run();} {} - } - Function {load_settings()} {open return_type void - } { - code {char *path; - -asprintf( &path, "%s/%s", config.user_config_dir, "view" ); - -((Fl_Menu_Settings*)menu_bar)->load( menu_bar->find_item( "&View" ), path ); - -free( path );} {} - } - Function {save_settings()} {open return_type void - } { - code {char *path; - -asprintf( &path, "%s/%s", config.user_config_dir, "view" ); - -((Fl_Menu_Settings*)menu_bar)->dump( menu_bar->find_item( "&View" ), path ); - -free( path );} {} - } - Function {draw_overlay( void *v )} {open protected return_type {static void} - } { - code {((UI*)v)->draw_overlay();} {} - } - Function {draw_overlay()} {open protected return_type void - } { - code {Canvas *c = current_canvas(); -if ( c ) - c->draw_overlay();} {} - } - Function {make_main_window()} {open - } { - Fl_Window main_window { - label {Non Sequencer} - callback {// Ignore escape -if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape ) - return; - -if ( maybe_save_song() ) - quit();} open - xywh {213 323 865 805} type Double color 47 resizable - code0 {o->color( FL_BACKGROUND_COLOR );} - code1 {o->draw_overlay_callback( &UI::draw_overlay, this );} - code2 {o->xclass( APP_NAME );} - class Overlay_Callback_Window size_range {700 509 0 0} visible - } { - Fl_Group {} {open - xywh {0 25 865 70} box FLAT_BOX - } { - Fl_Group {} {open - xywh {552 26 312 69} - code0 {o->resizable(0);} - } { - Fl_Value_Input {} { - label BPM - callback {transport.set_beats_per_minute( o->value() );} - xywh {825 39 35 19} labelsize 9 align 1 when 8 textsize 10 - code1 {transport.signal_tempo_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} - code2 {o->value( transport.beats_per_minute );} - } - Fl_Group {} { - label {Time Sig.} open - xywh {756 38 64 21} labelsize 9 - } { - Fl_Value_Input {} { - callback {transport.set_beats_per_bar( o->value() );} - xywh {756 39 24 19} textsize 10 - code0 {transport.signal_bpb_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} - code1 {o->value( transport.beats_per_bar );} - } - Fl_Box {} { - label {/} - xywh {780 38 14 21} - } - Fl_Value_Input {} { - callback {transport.set_beat_type( o->value() );} - xywh {795 39 24 19} textsize 10 - code0 {transport.signal_beat_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} - code1 {o->value( transport.beat_type );} - } - } - Fl_Choice record_mode_menu { - label {Record Mode} - callback {if ( ! transport.recording ) - config.record_mode = (record_mode_e)o->value(); -else - o->value( config.record_mode );} - xywh {555 39 105 19} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1 textsize 9 - } { - MenuItem {} { - label Merge - xywh {15 15 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label Overwrite - xywh {25 25 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label Layer - xywh {35 35 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label New - xywh {45 45 40 25} labelfont 3 labelsize 10 - } - } - Fl_Choice playback_mode_menu { - label {Playback &Mode} - xywh {665 39 85 19} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1 - } { - MenuItem {} { - label Pattern - callback {song.play_mode = PATTERN;} - xywh {5 5 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label Sequence - callback {song.play_mode = SEQUENCE;} - xywh {15 15 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label Trigger - callback {song.play_mode = TRIGGER;} - xywh {25 25 40 25} labelfont 3 labelsize 10 - } - MenuItem {} { - label Queue - callback {song.play_mode = QUEUE;} - xywh {0 0 40 24} labelfont 3 labelsize 10 - } - } - Fl_Pack {} {open - xywh {555 60 305 30} type HORIZONTAL - class Fl_Scalepack - } { - Fl_Button {} { - label Sequence - callback {tabs->value( sequence_tab ); - - -edit_menu->deactivate(); -menu_bar->redraw();} - xywh {565 70 68 15} type Radio shortcut 0x80031 selection_color 69 - } - Fl_Button {} { - label Phrase - callback {tabs->value( phrase_tab ); - -edit_menu->activate(); -menu_bar->redraw();} - xywh {575 80 68 5} type Radio shortcut 0x80032 selection_color 69 - } - Fl_Button {} { - label Pattern - callback {tabs->value( pattern_tab ); - -edit_menu->activate(); -menu_bar->redraw();} - xywh {585 90 68 0} type Radio shortcut 0x80033 value 1 selection_color 69 - } - } - } - Fl_Pack vmetro_widget { - label Metronome - xywh {160 27 390 61} type HORIZONTAL box UP_BOX color 40 selection_color 48 labelsize 33 align 0 resizable - code0 {o->box( FL_FLAT_BOX );} - class Visual_Metronome - } {} - Fl_Pack transport_controls_group {open - xywh {4 27 151 60} type HORIZONTAL - code0 {o->spacing( 2 );} - class Fl_Scalepack - } { - Fl_Button play_button { - label {@>} - callback {transport.toggle();} - xywh {10 29 43 38} shortcut 0x20 labeltype ENGRAVED_LABEL - } - Fl_Button rec_button { - label {@circle} - callback {transport.recording = o->value(); - - -if ( o->value() ) -{ - if ( config.record_mode == NEW ) - { - pattern *p = new pattern; - p->length( -1 ); - - pattern_canvas_widget->grid( p ); - } - - ((pattern*)pattern_canvas_widget->grid())->record( 0 ); - - o->labelcolor( FL_RED ); -} -else -{ - pattern::recording()->record_stop(); - - o->labelcolor( FL_WHITE ); -}} - xywh {60 29 43 38} type Toggle shortcut 0x80072 selection_color 47 labeltype ENGRAVED_LABEL when 1 - } - Fl_Button home_button { - label {@|<} - callback {transport.locate( 0 );} - xywh {110 29 43 38} shortcut 0xff50 labeltype ENGRAVED_LABEL - } - } - } - Fl_Tabs tabs { - callback {((Fl_Group*)o->value())->child( 0 )->take_focus();} open - xywh {-1 91 868 694} box FLAT_BOX color 47 labeltype SHADOW_LABEL labelsize 19 when 1 resizable - code0 {canvas_background_color = fl_rgb_color( 18, 18, 18 );} - } { - Fl_Group sequence_tab {open - xywh {0 91 865 692} box FLAT_BOX color 37 labeltype NO_LABEL labelsize 12 hide resizable - code0 {update_sequence_widgets();} - } { - Fl_Group {} {open - xywh {5 118 240 502} labelsize 12 - } { - Fl_Browser playlist_browser { - label Playlist - xywh {5 155 240 398} type Hold box EMBOSSED_BOX color 39 selection_color 30 labelsize 12 labelcolor 55 align 1 when 4 textsize 18 textcolor 95 resizable - code0 {static int widths[] = { 40, 30, 0 };} - code1 {o->column_widths( widths ); o->column_char( '\\t' );} - code2 {o->value( 1 );} - } - Fl_Button sequence_phrase_delete_button { - label Delete - callback {int val = playlist_browser->value(); - -if ( val > 1 ) -{ -// playlist_browser->value( playlist_browser->value() + 1 ); - - playlist->remove( val - 2 ); - - update_sequence_widgets(); - - if ( ! playlist_browser->value() ) - playlist_browser->value( playlist_browser->size() ); -}} - xywh {6 559 64 25} shortcut 0xffff color 88 labelcolor 23 - } - Fl_Button sequence_phrase_up_button { - label Up - callback {if ( playlist_browser->value() > 2 ) -{ - playlist->move( playlist_browser->value() - 2, UP ); - playlist_browser->value( playlist_browser->value() - 1 ); - update_sequence_widgets(); -}} - xywh {135 559 45 25} shortcut 0xffbf - } - Fl_Button sequence_phrase_down_button { - label Down - callback {if ( playlist_browser->value() > 1 ) -{ - playlist->move( playlist_browser->value() - 2, DOWN ); - playlist_browser->value( playlist_browser->value() + 1 ); - update_sequence_widgets(); -}} - xywh {185 559 58 25} shortcut 0xffc0 - } - Fl_Menu_Button sequence_phrase_choice { - label {Insert Phrase} - callback {playlist->insert( playlist_browser->value() - 1, o->value() + 1 ); - -update_sequence_widgets(); - -int val = playlist_browser->value(); - -if ( val ) - playlist_browser->value( playlist_browser->value() + 1 ); -else - playlist_browser->value( playlist_browser->size() );} open - xywh {5 590 235 30} color 63 - } {} - } - Fl_Input sequence_name_field { - label Name - callback {playlist->name( o->value() );} - xywh {10 109 235 27} color 48 labelsize 12 align 1 when 1 - } - Fl_Light_Button detach_button { - label Detach - callback {if ( o->value() ) -{ - Fl_Group *g = seq_detached_group; - seq_window->show(); - g->add( sequence_tab ); - sequence_tab->resize( g->x(), g->y(), g->w(), g->h() ); - tabs->do_callback(); - main_window->redraw(); -} -else -{ - seq_window->hide(); - tabs->insert( (Fl_Widget&)*sequence_tab, 0 ); - sequence_tab->resize( pattern_tab->x(), pattern_tab->y(), pattern_tab->w(), pattern_tab->h() ); - tabs->do_callback(); -}} - xywh {7 749 78 26} - } - Fl_Text_Editor sequence_notes_edit { - label {Notes:} - callback {playlist->notes( o->buffer()->text() );} - xywh {254 732 606 48} selection_color 48 labelsize 12 align 5 textcolor 94 - code0 {o->buffer( sequence_notes_buffer = new Fl_Text_Buffer );} - } - Fl_Box triggers_widget { - label Patterns - xywh {253 118 607 598} box FLAT_BOX color 48 labelsize 12 align 1 resizable - code0 {o->color( FL_BACKGROUND_COLOR );} - code1 {o->rows( 32 );} - class Triggers - } - Fl_Group progress_group { - callback {if ( ! o->visible_r() ) - return; - -phrase *p = phrase::phrase_by_number( playlist->playing() ); - -if ( p ) - phrase_progress->value( p->index() / (double)p->length() ); - -if ( playlist->length() ) - sequence_progress->value( playlist->index() / (double)playlist->length() );} open - xywh {10 649 233 66} - } { - Fl_Slider phrase_progress { - label Phrase - xywh {10 649 233 24} type Horizontal labelsize 12 align 1 - } - Fl_Slider sequence_progress { - label Sequence - callback {transport.locate( (tick_t)((double)playlist->length() * o->value()) );} - xywh {10 691 233 24} type Horizontal labelsize 12 align 1 - } - } - } - Fl_Group phrase_tab { - xywh {0 91 865 693} box FLAT_BOX color 47 labeltype NO_LABEL hide - code0 {update_phrase_widgets();} - } { - Fl_Box phrase_canvas_widget { - label Phrase - xywh {0 91 865 637} box FLAT_BOX color 37 labelsize 100 align 16 resizable - class Canvas - } - Fl_Group phrase_settings_group {open - xywh {0 728 865 55} box FLAT_BOX color 47 - } { - Fl_Input phrase_name_field { - label {name:} - callback {phrase_canvas_widget->grid()->name( strdup( o->value() ) ); - -// if the name changed.. -update_sequence_widgets();} - xywh {5 734 185 21} box ROUNDED_BOX color 49 labelfont 2 labelsize 12 labelcolor 55 align 20 textfont 2 textsize 12 - code0 {o->up_box( FL_ROUNDED_BOX );} - class Fl_Sometimes_Input - } - Fl_Light_Button phrase_mute_button { - label Mute - xywh {0 751 93 23} color 37 hide - } - Fl_Light_Button phrase_solo_button { - label Solo - xywh {106 751 87 23} color 37 hide - } - Fl_Text_Editor phrase_notes_edit { - label {Notes:} - callback {phrase_canvas_widget->grid()->notes( o->buffer()->text() );} - xywh {200 742 660 36} selection_color 48 labelsize 12 textcolor 94 resizable - code0 {o->buffer( phrase_notes_buffer = new Fl_Text_Buffer );} - } - Fl_Value_Slider phrase_number_spinner { - label {Phrase:} - callback {phrase *p = ((phrase *)phrase_canvas_widget->grid())->by_number( o->value() ); - -if ( p ) - phrase_canvas_widget->grid( p ); - -o->maximum( phrase::phrases() );} - xywh {45 760 140 18} type Horizontal labelsize 10 align 4 minimum 1 maximum 128 step 1 value 1 textsize 14 - } - } - } - Fl_Group pattern_tab {open - xywh {0 91 867 694} box FLAT_BOX color 47 labeltype NO_LABEL - code0 {update_pattern_widgets();} - } { - Fl_Box pattern_canvas_widget { - label Pattern - xywh {0 91 865 637} box FLAT_BOX color 37 labelsize 100 align 16 resizable - class Canvas - } - Fl_Group pattern_settings_group {open - xywh {0 730 867 55} box FLAT_BOX color 47 - } { - Fl_Group {} {open - xywh {5 733 420 44} - code0 {o->resizable(0);} - } { - Fl_Input pattern_name_field { - label {name:} - callback {pattern_canvas_widget->grid()->name( strdup( o->value() ) );} - xywh {5 734 185 21} box BORDER_BOX color 49 labelsize 12 align 20 when 8 textsize 12 textcolor 55 - code0 {o->up_box( FL_BORDER_BOX );} - class Fl_Sometimes_Input - } - Fl_Light_Button pattern_mute_button { - label Mute - callback {Grid *g = pattern_canvas_widget->grid(); - -g->mode( g->mode() == MUTE ? PLAY : MUTE ); - -o->value( g->mode() == MUTE ); - -pattern_solo_button->value( 0 );} - xywh {195 734 58 19} type Normal shortcut 0x6d color 37 labelsize 12 - } - Fl_Light_Button pattern_solo_button { - label Solo - callback {Grid *g = pattern_canvas_widget->grid(); - -g->mode( g->mode() == SOLO ? PLAY : SOLO ); - -o->value( g->mode() == SOLO ); - -pattern_mute_button->value( 0 );} - xywh {195 758 58 19} type Normal shortcut 0x73 color 37 labelsize 12 - } - Fl_Value_Slider pattern_number_spinner { - label Pattern - callback {pattern *p = ((pattern *)pattern_canvas_widget->grid())->by_number( o->value() ); - -if ( p ) - pattern_canvas_widget->grid( p ); - -o->maximum( pattern::patterns() );} - xywh {45 759 140 18} type Horizontal labelsize 10 align 4 minimum 1 maximum 128 step 1 value 1 - } - Fl_Button pattern_selection_mode { - label Select - callback {pattern_canvas_widget->selection_mode( o->value() );} - tooltip {Enable selection mode (you can also just hold down shift and drag the mouse)} xywh {260 733 45 44} type Toggle selection_color 5 labelsize 10 - } - Fl_Value_Slider velocity_slider { - label Velocity - callback {pattern_canvas_widget->selected_velocity( o->value() );} selected - xywh {310 742 110 18} type {Horz Fill} labelsize 10 align 1 maximum 127 value 64 textsize 9 - } - } - Fl_Group {} {open - xywh {455 731 409 54} - } { - Fl_Output mapping_text { - label Mapping - xywh {535 761 105 19} labelsize 10 align 20 textsize 11 - } - Fl_Menu_Button mapping_menu { - label {@>} - callback {mapping_text->value( o->text() ); - - -char picked[80]; -mapping_menu->item_pathname(picked, sizeof(picked)-1 ); - -if ( 0 == strncmp( picked, "Instrument", strlen( "Instrument" ) ) ) -{ - ((pattern*)pattern_canvas_widget->grid())->mapping.open( Mapping::INSTRUMENT, o->text() ); - - pattern_canvas_widget->changed_mapping(); - - pattern_key_combo->deactivate(); -} -else -if ( 0 == strncmp( picked, "Scale", strlen( "Scale" ) ) ) -{ - ((pattern*)pattern_canvas_widget->grid())->mapping.open( Mapping::SCALE, o->text() ); - - pattern_canvas_widget->changed_mapping(); - - pattern_key_combo->activate(); -}} open - xywh {640 761 30 19} labeltype NO_LABEL labelsize 10 textsize 12 - code0 {update_mapping_menu();} - } { - Submenu mapping_scale_menu { - label Scale open - xywh {25 25 74 25} - } {} - Submenu mapping_instrument_menu { - label Instrument open - xywh {10 10 74 25} - } {} - } - Fl_Choice pattern_key_combo { - label {&Key} - callback {((pattern*)pattern_canvas_widget->grid())->mapping.key( o->value() ); - -pattern_canvas_widget->changed_mapping();} - xywh {700 761 75 19} down_box BORDER_BOX labelsize 10 when 1 textsize 11 - } { - MenuItem {} { - label C - xywh {30 30 40 25} labelsize 11 - } - MenuItem {} { - label {C\#/Db} - xywh {40 40 40 25} labelsize 11 - } - MenuItem {} { - label D - xywh {50 50 40 25} labelsize 11 - } - MenuItem {} { - label {D\#/Eb} - xywh {60 60 40 25} labelsize 11 - } - MenuItem {} { - label E - xywh {70 70 40 25} labelsize 11 - } - MenuItem {} { - label F - xywh {80 80 40 25} labelsize 11 - } - MenuItem {} { - label {F\#/Gb} - xywh {90 90 40 25} labelsize 11 - } - MenuItem {} { - label G - xywh {100 100 40 25} labelsize 11 - } - MenuItem {} { - label {G\#} - xywh {110 110 40 25} labelsize 11 - } - MenuItem {} { - label A - xywh {0 0 40 25} labelsize 11 - } - MenuItem {} { - label {A\#/Bb} - xywh {10 10 40 25} labelsize 11 - } - MenuItem {} { - label B - xywh {20 20 40 25} labelsize 11 - } - } - Fl_Choice pattern_note_combo { - label {&Note 1/} - callback {((pattern*)pattern_canvas_widget->grid())->note( atoi( o->menu()[ o->value() ].text ));} - xywh {715 736 45 19} down_box BORDER_BOX labelsize 10 when 1 textsize 12 - } { - MenuItem {} { - label 1 - xywh {0 0 40 25} labelsize 11 - } - MenuItem {} { - label 2 - xywh {10 10 40 25} labelsize 11 - } - MenuItem {} { - label 4 - xywh {20 20 40 25} labelsize 11 - } - MenuItem {} { - label 8 - xywh {30 30 40 25} labelsize 11 - } - MenuItem {} { - label 16 - xywh {40 40 40 25} labelsize 11 - } - MenuItem {} { - label 32 - xywh {50 50 40 25} labelsize 11 - } - MenuItem {} { - label 64 - xywh {60 60 40 25} labelsize 11 divider - } - MenuItem {} { - label 3 - xywh {60 60 40 25} labelsize 11 - } - MenuItem {} { - label 6 - xywh {70 70 40 25} labelsize 11 - } - MenuItem {} { - label 12 - xywh {80 80 40 25} labelsize 11 - } - MenuItem {} { - label 24 - xywh {90 90 40 25} labelsize 11 - } - } - Fl_Choice pattern_res_combo { - label {&Resolution 1/} - callback {pattern_canvas_widget->grid()->resolution( atoi( o->menu()[ o->value() ].text ));} - xywh {615 736 55 19} down_box BORDER_BOX labelsize 10 when 1 textsize 12 - } { - MenuItem {} { - label 1 - xywh {40 40 40 25} labelsize 11 - } - MenuItem {} { - label 2 - xywh {50 50 40 25} labelsize 11 - } - MenuItem {} { - label 4 - xywh {30 30 40 25} labelsize 11 - } - MenuItem {} { - label 8 - xywh {40 40 40 25} labelsize 11 - } - MenuItem {} { - label 16 - xywh {50 50 40 25} labelsize 11 - } - MenuItem {} { - label 32 - xywh {60 60 40 25} labelsize 11 - } - MenuItem {} { - label 64 - xywh {80 80 40 25} labelsize 11 - } - MenuItem {} { - label 128 - xywh {90 90 40 25} labelsize 11 divider - } - MenuItem {} { - label 3 - xywh {70 70 40 25} labelsize 11 - } - MenuItem {} { - label 6 - xywh {80 80 40 25} labelsize 11 - } - MenuItem {} { - label 12 - xywh {90 90 40 25} labelsize 11 - } - MenuItem {} { - label 24 - xywh {100 100 40 25} labelsize 11 - } - } - Fl_Choice pattern_channel_choice { - label {Channel:} - callback {((pattern *)pattern_canvas_widget->grid())->channel( o->value() );} open - xywh {810 735 47 19} down_box BORDER_BOX labelsize 10 textsize 12 - code0 {char pat[3]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} - } {} - Fl_Choice pattern_port_choice { - label {Port:} - callback {((pattern *)pattern_canvas_widget->grid())->port( o->value() );} open - xywh {810 760 47 19} down_box BORDER_BOX labelsize 10 textsize 12 - code0 {char pat[3]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} - } {} - Fl_Input_Choice pattern_bars_choice { - label {Bars:} - callback {((pattern *)pattern_canvas_widget->grid())->bars( atoi( o->value() ) );} open - xywh {486 736 55 19} labelsize 10 textsize 12 - code0 {char pat[4]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} - code1 {for ( int i = 32; i <= 256; i <<= 1 ) { snprintf( pat, sizeof(pat), "%i", i ); o->add( pat ); }} - } {} - Fl_Box {} { - xywh {455 735 0 46} labelsize 8 align 1 resizable - } - } - } - } - } - Fl_Group {} {open - xywh {0 784 865 23} - } { - Fl_Box status { - label status - xywh {1 784 782 23} box UP_BOX align 84 - code0 {o->label( NULL );} - } - Fl_Box transport_state { - label state - callback {const char *s = "INVALID"; - -if ( transport.master ) - s = "Master"; -else if ( transport.valid ) - s = "Slave"; - -if ( s != o->label() ) -{ - o->label( s ); - if ( ! strcmp( s, "INVALID" ) ) - o->color( fl_darker( FL_RED ) ); - else - o->color( FL_BACKGROUND_COLOR ); -}} - xywh {783 784 82 23} box THIN_UP_BOX align 64 - } - } - Fl_Group {} {open - xywh {0 0 865 24} - } { - Fl_Menu_Bar menu_bar {open - xywh {0 0 865 24} color 47 resizable - } { - Submenu {} { - label {&File} open - xywh {0 0 100 20} color 37 - } { - MenuItem menu_new { - label {&New} - callback {if ( maybe_save_song() ) -{ - init_song(); - - // Sync the GUI. - update_pattern_widgets(); - update_sequence_widgets(); - update_phrase_widgets(); - - - gui_status( "New song." ); -}} - xywh {0 0 40 25} - } - MenuItem menu_open { - label {&Open} - callback {char *name = fl_file_chooser( "Open File", "Non Files (*.non)", NULL, 0 ); - -if ( name ) -{ - if ( ! load_song( name ) ) - fl_alert( "Could not load song!" ); - else - gui_status( "Song opened." ); - - update_sequence_widgets(); - update_pattern_widgets(); - update_phrase_widgets(); - - playback_mode_menu->value( song.play_mode ); - playback_mode_menu->redraw(); -}} - xywh {0 0 40 25} shortcut 0x4006f color 37 - } - MenuItem menu_save { - label {&Save} - callback {save_dialog( song.filename );} - xywh {0 0 40 25} shortcut 0x40073 color 37 deactivate - code0 {song.signal_dirty.connect( sigc::mem_fun( o, &Fl_Menu_Item::activate ) );} - code1 {song.signal_clean.connect( sigc::mem_fun( o, &Fl_Menu_Item::deactivate ) );} - } - MenuItem menu_save_as { - label {Save &As} - callback {save_dialog( NULL );} - xywh {0 0 40 25} - } - MenuItem {} { - label {&Import} - callback {char *name = fl_file_chooser( "MIDI Import", "MIDI Files (*.mid)", NULL, 0 ); - -if ( ! name ) - return; - -smf f; - -if ( ! f.open( name, smf::READ ) ) -{ - fl_message( "could not open file" ); - return; -} - -f.read_header(); - -switch ( f.format() ) -{ - case 0: - if ( ! pattern::import( &f, 0 ) ) - fl_message( "Error importing MIDI" ); - break; - case 1: case 2: - { - char **sa = f.track_listing(); - - if ( sa && *sa ) - { - List_Chooser tc( "Select tracks to import:", "Import" ); - - char *s; - for ( int i = 0; (s = sa[i]); ++i ) - { - tc.add( s ); - free( s ); - } - - free( sa ); - - tc.show(); - - while( tc.shown() ) - Fl::wait(); - - int n = 0; - for ( int i = 1; i <= tc.browser->size(); ++i ) - { - if ( tc.browser->selected( i ) ) - { - if ( pattern::import( &f , i - 1 ) ) - ++n; - else - WARNING( "error importing track %d", i - 1 ); - } - - } - // fl_message( "%d patterns imported.", n ); - gui_status( "Imported %d tracks as patterns", n ); - } - - break; - } -}} - xywh {0 0 40 25} - code0 {\#include "../smf.H"} - } - MenuItem {} { - label {&Export} - callback {// Fl_File_Chooser::custom_filter_label = "*.mid"; - -Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "MIDI Files (*.mid)", Fl_File_Chooser::CREATE, "MIDI Export" ); - -fc->show(); - -// wait for user to make a choice -while( fc->shown() ) - Fl::wait(); - -if ( ! fc->value() ) - return; - -if ( tabs->value() == pattern_tab ) - ((pattern*)pattern_canvas_widget->grid())->save( fc->value() );} - xywh {0 0 40 25} - code0 {\#include } - } - MenuItem {} { - label {&Quit} - callback {main_window->do_callback();} - xywh {0 0 40 25} shortcut 0x40071 color 37 - } - } - Submenu {} { - label {&View} open - xywh {10 10 74 25} color 37 - } { - MenuItem {} { - label {&Metronome} - callback {int val = o->menu()[ o->value() ].value(); - -if ( val ) - vmetro_widget->show(); -else - vmetro_widget->hide();} - xywh {0 0 40 25} type Toggle value 1 - } - MenuItem {} { - label {&Compacted} - callback {int val = o->menu()[ o->value() ].value(); - -pattern_canvas_widget->row_compact( val ? Canvas::ON : Canvas::OFF ); - -pattern_canvas_widget->redraw();} - xywh {10 10 40 25} type Toggle value 1 - } - MenuItem {} { - label {&Follow Playhead} - callback {int val = o->menu()[ o->value() ].value(); - -config.follow_playhead = val ? true : false;} - xywh {10 10 40 25} type Toggle value 1 - } - MenuItem {} { - label {&Theme} - callback {fl_theme_chooser();} - xywh {0 0 40 24} - } - } - Submenu {} { - label {&Help} open - xywh {100 0 74 25} color 37 - } { - MenuItem {} { - label {&Manual} - callback {show_help_dialog( "MANUAL" );} - xywh {10 10 40 25} divider - } - MenuItem {} { - label {&About} - callback {About_Dialog ab( PIXMAP_PATH "/non-sequencer/icon-256x256.png" ); - - ab.logo_box->label( VERSION ); - - ab.title->label( "Non Sequencer" ); - - ab.copyright->label( "Copyright (C) 2007-2013 Jonathan Moore Liles" ); - ab.credits->label( "Non Sequencer was written from scratch by\\nJonathan Moore Liles for his own use\\n(see the manual).\\n\\nNobody planned. Nobody helped.\\nYou can help now by donating time, money,\\nand/or replacing the rest of Linux Audio\\nwith fast, light, reliable alternatives.\\n" ); - - ab.website_url->label( "http://non.tuxfamily.org" ); - -ab.run();} - xywh {0 0 40 25} color 37 - code0 {\#include "../non.H"} - } - } - Submenu edit_menu { - label {&Edit} open - xywh {0 0 68 18} - } { - MenuItem {} { - label {Add New} - callback {Grid *g = current_canvas()->grid()->create(); - -current_canvas()->grid( g ); - -update_pattern_widgets(); -update_sequence_widgets(); -update_phrase_widgets();} - xywh {0 0 34 18} shortcut 0x61 - } - MenuItem {} { - label Previous - callback {if ( tabs->value() == pattern_tab ) -{ - pattern_number_spinner->value( max( 0, (int)pattern_number_spinner->value() - 1 ) ); - pattern_number_spinner->do_callback(); -} -else -{ - phrase_number_spinner->value( max( 0, (int)phrase_number_spinner->value() - 1 ) ); - phrase_number_spinner->do_callback(); -}} - xywh {10 10 34 18} shortcut 0x5b - } - MenuItem {} { - label Next - callback {if ( tabs->value() == pattern_tab ) -{ - pattern_number_spinner->value( min( 127, (int)pattern_number_spinner->value() + 1 )); - pattern_number_spinner->do_callback(); -} -else -{ - phrase_number_spinner->value( min( 127, (int)phrase_number_spinner->value() + 1 )); - phrase_number_spinner->do_callback(); -}} - xywh {20 20 34 18} shortcut 0x5d - } - MenuItem {} { - label Duplicate - callback {Canvas *w = current_canvas(); - -w->grid( w->grid()->clone() ); - -// number of phrases may have changed. -ui->update_sequence_widgets();} - xywh {30 30 34 18} shortcut 0x64 - } - MenuItem {} { - label {Delete Selected} - callback {Canvas *w = current_canvas(); - -w->grid()->delete_selected();} - xywh {50 50 34 18} shortcut 0xffff - } - MenuItem {} { - label Clear - callback {Canvas *w = current_canvas(); - -w->grid()->clear();} - xywh {60 60 34 18} shortcut 0x1ffff - } - MenuItem {} { - label {Edit Events} - callback {event_editor( pattern_canvas_widget->grid() );} - xywh {10 10 40 25} - } - MenuItem {} { - label {Select All} - callback {Canvas *w = current_canvas(); - -w->grid()->select_all();} - xywh {70 70 34 18} shortcut 0x40061 - } - MenuItem {} { - label {Select None} - callback {Canvas *w = current_canvas(); - -w->grid()->select_none();} - xywh {80 80 34 18} shortcut 0x50061 - } - MenuItem {} { - label {Invert Selection} - callback {Canvas *w = current_canvas(); - -w->grid()->invert_selection();} - xywh {90 90 34 18} shortcut 0x50069 - } - MenuItem {} { - label Cut - callback {Canvas *w = current_canvas(); - -w->cut();} - xywh {110 110 34 18} shortcut 0x40078 - } - MenuItem {} { - label Copy - callback {Canvas *w = current_canvas(); - -w->copy();} - xywh {100 100 34 18} shortcut 0x40063 - } - MenuItem {} { - label Paste - callback {Canvas *w = current_canvas(); - -w->paste();} - xywh {120 120 34 18} shortcut 0x40076 - } - MenuItem {} { - label Undo - callback {Canvas *w = current_canvas(); - -w->grid()->undo();} - xywh {110 110 34 18} shortcut 0x4007a - } - } - } - Fl_Button sm_indicator { - label SM - xywh {825 5 35 15} box ROUNDED_BOX down_box ROUNDED_BOX color 46 selection_color 93 labelfont 3 labelcolor 39 deactivate - } - } - } - } - Function {make_seq_window()} {} { - Fl_Window seq_window { - label {Non Sequencer - Sequence} - callback {sequence_tab->activate(); -o->hide(); -detach_button->value( 0 );} - xywh {681 189 876 675} type Double hide resizable - } { - Fl_Group seq_detached_group {open - xywh {0 0 876 675} resizable - } {} - } - } - Function {update_pattern_widgets()} {} { - code {if ( ! pattern_settings_group ) - return; - -if ( !pattern_canvas_widget) - return; - -pattern *g = (pattern *)pattern_canvas_widget->grid(); - -if ( !g ) - return; - -pattern_number_spinner->value( g->number() ); -pattern_name_field->value( g->name() ); -pattern_channel_choice->value( g->channel() ); -pattern_port_choice->value( g->port() ); -pattern_solo_button->value( g->mode() == SOLO ); -pattern_mute_button->value( g->mode() == MUTE ); -pattern_selection_mode->value( pattern_canvas_widget->selection_mode() ); -{ - char pat[5]; - snprintf( pat, sizeof(pat), "%i", g->bars() ); - pattern_bars_choice->value( pat ); -} - -if ( g->mapping.key() == -1 ) - pattern_key_combo->deactivate(); -else -{ - pattern_key_combo->activate(); - pattern_key_combo->value( g->mapping.key() ); -} - -mapping_text->value( g->mapping.name() ); - - - -pattern_note_combo->value( find_numeric_menu_item( menu_pattern_note_combo, g->note() )); -pattern_res_combo->value( find_numeric_menu_item( menu_pattern_res_combo, g->resolution() )); -/* -if ( g->notes() ) - pattern_notes_buffer->text( g->notes() ); -else - pattern_notes_buffer->text( strdup( "" ) ); -*/ -pattern_settings_group->redraw();} {} - } - Function {update_phrase_widgets()} {} { - code {if ( ! phrase_canvas_widget ) - return; - -phrase *g = (phrase *)phrase_canvas_widget->grid(); - -if ( ! g ) - return; - -g->viewport.y = 0; -g->viewport.h = pattern::patterns(); -phrase_canvas_widget->resize_grid(); -phrase_canvas_widget->changed_mapping(); -phrase_number_spinner->value( g->number() ); -phrase_name_field->value( g->name() ); -phrase_solo_button->value( g->mode() == SOLO ); -phrase_mute_button->value( g->mode() == MUTE ); - -if ( g->notes() ) - phrase_notes_buffer->text( g->notes() ); -else - phrase_notes_buffer->text( strdup( "" ) ); - -phrase_settings_group->redraw();} {} - } - Function {update_sequence_widgets()} {} { - code {if ( playlist->notes() ) - sequence_notes_buffer->text( playlist->notes() ); -else - sequence_notes_buffer->text( strdup( "" ) ); - -sequence_name_field->value( playlist->name() ); - -sequence_phrase_choice->clear(); - -for ( int i = 1; i <= phrase::phrases(); i++ ) -{ - phrase *p = phrase::phrase_by_number( i ); - - if ( p ) - sequence_phrase_choice->add( p->name() ); -} - - -Fl_Browser *o = playlist_browser; - -int val = o->value(); - -o->clear(); - -char *s = playlist->dump(); - -char *l = strtok( s, "\\n" ); - -o->add( "@b@C2Bar\\t@b@C2\#\\t@b@C2Name" ); - -if ( ! l ) - return; - -o->add( l ); - -while ( ( l = strtok( NULL, "\\n" ) ) ) -{ - o->add( l ); -} - -o->value( val ); - -free( s ); - - -if ( playback_mode_menu ) - playback_mode_menu->value( song.play_mode );} {} - } - Function {update_mapping_menu()} {} { - code {char **sa = Instrument::listing(); - -if ( sa ) -{ - - for ( int i = 0; sa[i]; i++ ) - { - char pat[512]; - snprintf( pat, 512, "Instrument/%s", sa[i] ); - mapping_menu->add( pat, 0, 0, 0, 0 ); - free( sa[i] ); - } - free( sa ); -} - -sa = Scale::listing(); -for ( int i = 0; sa[i]; i++ ) -{ - char pat[512]; - snprintf( pat, 512, "Scale/%s", sa[i] ); - mapping_menu->add( pat, 0, 0, 0, 0 ); - free( sa[i] ); -} -free( sa );} {} - } - Function {update_canvas_widgets()} {return_type {static void} - } { - code {if ( ui->pattern_canvas_widget->grid() ) - ui->update_pattern_widgets(); - - if ( ui->phrase_canvas_widget->grid() ) - ui->update_phrase_widgets();} {} - } - Function {find_numeric_menu_item( const Fl_Menu_Item *menu, int n )} {return_type {static int} - } { - code {for ( unsigned int i = 0; menu[i].text; i++ ) -{ - if ( atoi( menu[i].text ) == n ) - return i; -} - -return 0;} {} - } - Function {save_dialog( const char *name )} {return_type void - } { - code {if ( ! name ) -{ - - Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "Non Sequences (*.non)", Fl_File_Chooser::CREATE, "Save sequence" ); - - fc->show(); - - // wait for user to make a choice - while( fc->shown() ) - Fl::wait(); - - if ( ! fc->value() ) - return; - - name = fc->value(); -} - -if ( ! save_song( name ) ) - fl_alert( "Could not save song" ); -else - gui_status( "Saved." );} {} - } - Function {show_help_dialog( const char *file )} {return_type void - } { - code {char pat[256]; - -snprintf( pat, 256, "file://%s/non-sequencer/%s.html", DOCUMENT_PATH, file ); - -open_url( pat );} {} - } - Function {maybe_save_song()} {return_type bool - } { - code {if ( song.dirty() ) -{ - int c = fl_choice( "Song has been modified since last save. What shall I do?", "&Cancel", "&Save", "&Discard" ); - - switch ( c ) - { - case 0: - return false; - case 1: - /* SAVE */ - save_dialog( song.filename ); - break; - case 2: - break; - } -} - -return true;} {} - } - Function {switch_to_pattern( int n )} {return_type void - } { - code {pattern *p = pattern::pattern_by_number( n ); - -if ( p ) -{ - - - - tabs->value( pattern_tab ); - - pattern_canvas_widget->take_focus(); - - pattern_canvas_widget->grid( p ); - -// update_pattern_widgets(); -}} {} - } - Function {edit_instrument_row( Instrument *i, int n )} {return_type void - } { - code {Instrument_Editor ie; - -ie.set( i, n ); - -ie.run();} {} - } - Function {current_canvas()} {open return_type {Canvas*} - } { - code {if ( tabs->value() == pattern_tab ) - return pattern_canvas_widget; -else if ( tabs->value() == phrase_tab ) - return phrase_canvas_widget; -else - return NULL;} {} - } -} - -class Instrument_Editor {} { - Function {Instrument_Editor()} {open return_type void - } { - code {make_window();} {} - } - decl {Instrument *_inst;} {private local - } - decl {int _note;} {private local - } - Function {make_window()} {open - } { - Fl_Window window { - label {Instrument Editor} - callback {done->do_callback();} open - xywh {670 458 335 190} type Double hide - } { - Fl_Box {} { - label {Instrument Row} - xywh {8 15 321 28} box ROUNDED_BOX color 94 labelsize 22 labelcolor 39 - } - Fl_Input name_field { - label Name - callback {_inst->note_name( _note, strdup( o->value() ) );} - xywh {10 70 321 25} selection_color 48 align 1 when 1 textcolor 32 - } - Fl_Value_Slider volume_slider { - label {Volume %} - callback {_inst->velocity( _note, o->value() );} - xywh {10 112 321 27} type Horizontal align 1 maximum 100 step 1 textsize 14 - } - Fl_Value_Output note_field { - label {Note:} - xywh {52 158 43 24} - } - Fl_Return_Button done { - label Done - callback {if ( _inst ) - _inst->save(); - -window->hide();} - xywh {255 157 76 25} - } - } - } - Function {set( Instrument *i, int n )} {open return_type void - } { - code {_inst = i; -_note = n; - -volume_slider->value( i->velocity( n ) ); -name_field->value( i->note_name( n ) ); -note_field->value( n );} {} - } - Function {run()} {open return_type void - } { - code {window->show(); - -while ( window->shown() ) - Fl::wait();} {} - } -} - -class Trigger {: {public Fl_Progress} -} { - Function {Trigger( int X, int Y, int W, int H, const char *L =0) : Fl_Progress( X, Y, W, H, L )} {open - } { - code {minimum( 0 ); -maximum( 1 ); -//angles( 0, 360 ); -// type( Fl_Dial::ARC_DIAL ); -// type(FL_VERTICAL);} {} - } - Function {handle( int m )} {open return_type int - } { - code {int r = 0; - -switch ( m ) -{ - case FL_PUSH: - { - switch ( Fl::event_button() ) - { - case 1: - { - pattern *p = pattern::pattern_by_number( atoi( label() ) ); - - if ( p ) - { - if ( TRIGGER == song.play_mode ) - { - if ( p->playing() ) - p->stop(); - else - p->trigger(); - } - else - { - if ( p->mode() == PLAY ) - p->mode( MUTE ); - else - p->mode( PLAY ); - } - } - - break; - } - case 2: - { - pattern *p = pattern::pattern_by_number( atoi( label() ) ); - - if ( p ) - { - if ( p->mode() != SOLO ) - p->mode( SOLO ); - else - p->mode( PLAY ); - } - - break; - } - case 3: - { - ui->switch_to_pattern( atoi( label() ) ); - } - break; - } - r = 1; - break; - } - case FL_RELEASE: - do_callback(); - r = 1; - break; - case FL_DRAG: - r = 1; - break; - default: - r = Fl_Widget::handle( m ); - break; -} - - -return r;} {} - } -} - -widget_class Triggers { - xywh {390 620 335 390} type Double hide - code0 {\#include } - code1 {populate();} - class Fl_Group -} { - Function {populate( void )} {open private return_type void - } { - code {_timer = 0; - - for ( int i = 0; i < 128; i++ ) - { - Trigger *b = new Trigger( 1,1,1,1 ); - - char pat[4]; - - sprintf( pat, "%d",i +1); - b->label( strdup( pat ) ); - b->labelsize( 8 ); - b->color2( FL_GRAY ); - b->box( FL_FLAT_BOX ); -// b->down_box( FL_ROUNDED_BOX ); - b->selection_color( FL_GREEN ); - b->color( FL_BLACK ); - b->color2( FL_GREEN ); - b->align( FL_ALIGN_CENTER ); - - add( b ); - }} {} - } - Function {update( void )} {open return_type void - } { - code {++_timer; - - if ( !visible_r() ) - return; - -if ( ! takesevents() ) - return; - - Fl_Color mode_color[3]; - - mode_color[PLAY] = fl_color_average( FL_GRAY, FL_GREEN, 0.5 ); -// mode_color[PLAY] = fl_color; - mode_color[MUTE] = FL_LIGHT2; - mode_color[SOLO] = fl_color_average( FL_GRAY, FL_RED, 0.5 ); - -if ( ! _rows ) - return; - -for ( int i = 0; i < MAX_PATTERN; i++ ) -{ - Trigger *b = (Trigger*)child( i ); - - if ( i >= pattern::patterns() ) - { - b->color( FL_BLACK ); - b->value( 0 ); - continue; - } - - pattern *p = pattern::pattern_by_number( i + 1 ); - - if ( p->playing() ) - { - b->color( FL_GRAY ); - - b->selection_color( mode_color[ p->mode() ] ); - - if ( p->queue() >= 0 ) - { - if ( _timer % 16 < 8 ) - { - b->color( mode_color[ p->queue() ] ); - } - } - - b->value( (double)p->index() / p->length() ); - } - else - { - b->value( 0 ); - } - -}} {} - } - decl {unsigned long _timer;} {private local - } - decl {int _rows;} {private local - } - Function {rows(int v)} {open return_type void - } { - code {_rows = v; -redraw();} {} - } - Function {draw()} {open return_type void - } { - code {int _cols = 128 / _rows; - -int bw = w() / _cols; -int bh = h() / _rows; - -int t = 0; -for ( int i = 0; i < _rows; i++ ) - for ( int j = 0; j < _cols ; j++, t++ ) - child( t )->resize( x() + (bw * j), y() + (bh * i), bw, bh ); - -Fl_Group::draw();} {} - } - decl {\#include } {private local - } -} - -class List_Chooser {} { - Function {List_Chooser( const char *name, const char *action )} {} { - Fl_Window window {open - xywh {525 313 310 545} type Single hide resizable non_modal size_range {310 524 0 0} - } { - Fl_Browser browser { - label name - xywh {5 26 300 480} type Multi box THIN_DOWN_BOX color 32 selection_color 0 align 1 textcolor 55 resizable - code0 {o->label( name );} - } - Fl_Group {} {open - xywh {5 505 300 39} - } { - Fl_Button {} { - label Cancel - callback {browser->clear(); -window->hide();} - xywh {5 513 75 27} - } - Fl_Return_Button button { - label action - callback {window->hide();} - xywh {115 513 190 27} - code0 {o->label( action );} - } - } - } - } - Function {show()} {open - } { - code {window->show();} {} - } - Function {shown()} {open return_type bool - } { - code {return window->shown();} {} - } - Function {add( const char *item )} {open - } { - code {browser->add( item );} {} - } -} - -decl {float status_intensity;} {private local -} - -Function {fade_status(void*)} {private return_type {static void} -} { - code {ui->status->labelcolor( fl_color_average( FL_FOREGROUND_COLOR, FL_BACKGROUND_COLOR, status_intensity ) ); - - status_intensity -= 0.01f; - - ui->status->redraw(); - - if ( status_intensity >= 0.01f ) - Fl::repeat_timeout( 1 / 15.0f, fade_status );} {} -} - -Function {gui_status( const char *fmt, ... )} {C return_type void -} { - code {va_list args; - - static char pat[256]; - - if ( fmt ) - { - va_start( args, fmt ); - vsnprintf( pat, 256, fmt, args ); - va_end( args ); - } - - ui->status->label( pat ); - ui->status->redraw(); - - status_intensity = 1.0f; - Fl::remove_timeout( fade_status ); - Fl::add_timeout( 1 / 15.0f, fade_status );} {} -} diff --git a/sequencer/src/instrument.C b/sequencer/src/instrument.C deleted file mode 100644 index ef14f24..0000000 --- a/sequencer/src/instrument.C +++ /dev/null @@ -1,330 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include - -#include "instrument.H" -#include "common.h" -#include "const.h" -#include "config.h" - -#include "non.H" - -#include -#include - - -#include - -#include - -#include -using namespace MIDI; - -using std::list; -using std::string; - -/****** - Instrument definition file format is thus: - - "Name", n, v - - Where /n/ is a note number from 0 to 127 and /v/ is a percentage of - volume. - - When a system installed instrument definition is modified, the - modified version is saved in the user's $HOME. Therefore, when - loading instruments, user defined instruments always hide system - defined instruments of the same name. - -*/ - -list Instrument::instruments; - -Instrument::Instrument ( const char *name ) -{ - - for ( int i = 0; i < 128; i++ ) - { - _map[i].name = NULL; - _map[i].velocity = 100; - } - - if ( name ) - { - _name = strdup( name ); - - read( name ); - } - else - { - _name = strdup( "not an instrument" ); - _height = 0; - } - - Instrument::instruments.push_front( this ); -} - -Instrument * -Instrument::open ( const char *name ) -{ - list ::iterator i = Instrument::instruments.begin(); - - if ( name ) - { - for ( ; i != Instrument::instruments.end(); i++ ) - if ( 0 == strcmp( (*i)->_name, name ) ) - return *i; - } - - return new Instrument ( name ); -} - -void -Instrument::note_name ( int n, char *s ) -{ - if ( _map[ n ].name ) - free( _map[ n ].name ); - - _map[ n ].name = s; - - _dirty = true; -} - -void -Instrument::velocity ( int n, int v ) -{ - _map[ n ].velocity = v; - - _dirty = true; -} - -/** Translate event, should only be passed NOTE ON/OFF events, returns - true if note is valid for this mapping */ -bool -Instrument::translate ( midievent *e ) const -{ - if ( ! note_name( e->note() ) ) - return false; - - e->note_velocity( e->note_velocity() * _map[ e->note() ].velocity / 100 ); - - return true; -} - -const char * -Instrument::note_name ( int n ) const -{ - return _map[ n ].name; -} - -int -Instrument::height ( void ) const -{ - return _height; -} - -int -Instrument::velocity ( int n ) const -{ - return _map[ n ].velocity; -} - -bool -Instrument::read ( const char *s ) -{ - FILE *fp; - - char pat[512]; - - sprintf( pat, "%s%s.inst", config.user_config_dir, s ); - - if ( ! ( fp = fopen( pat, "r" ) ) ) - { - - sprintf( pat, "%s/%s/%s.inst", SYSTEM_PATH, INSTRUMENT_DIR, s ); - - if ( ! ( fp = fopen( pat, "r" ) ) ) - return false; - } - - struct i_map m; - char namebuf[256]; - int note, velocity; - - int n = 0; - while ( 0 < fscanf( fp, "\"%[^\"]\", %d, %d\n", (char*)&namebuf, ¬e, &velocity ) ) n++; - - rewind( fp ); - - MESSAGE( "reading %d lines from instrument file \"%s\"", n, s ); - - int i; - for ( i = 0; i < n; i++ ) - { - fscanf( fp, "\"%[^\"]\", %d, %d\n", (char *)&namebuf, ¬e, &velocity ); - - m.name = strdup( namebuf ); - - if ( velocity > 100 ) - { - WARNING( "invalid volume percentage in instrument definition"); - m.velocity = 100; - } - else - m.velocity = velocity; - - DMESSAGE( "name: \"%s\", note: %d, velocity: %d%%", m.name, note, m.velocity ); - - _map[ note ] = m; - } - - _height = n; - - fclose( fp ); - - return true; -} - -bool -Instrument::write ( const char *s ) const -{ - FILE *fp; - - char pat[512]; - - sprintf( pat, "%s/%s.inst", config.user_config_dir, s ); - - if ( ! ( fp = fopen( pat, "w" ) ) ) - return false; - - int n = 0; - for ( int i = 0; i < 127; ++i ) - { - if ( _map[ i ].name ) - { - fprintf( fp, "\"%s\", %d, %d\n", _map[ i ].name, i, _map[ i ].velocity ); - ++n; - } - } - - DMESSAGE( "wrote %d lines to instrument file \"%s\"", n, pat ); - - fclose( fp ); - - return true; -} - -void -Instrument::save ( void ) const -{ - if ( _dirty ) - write( _name ); - - _dirty = false; -} - -static int -instrument_filter ( const struct dirent *d ) -{ - char suffix[] = "*.inst"; - - return 0 == fnmatch( suffix, d->d_name, 0 ); -} - -static -list * -get_listing( const char *dir ) -{ - list *sl = new list ; - - struct dirent **names; - int n; - - if ( 0 > ( n = scandir( dir, &names, instrument_filter, alphasort ) ) ) - { - WARNING( "couldn't open instrument directory" ); - return NULL; - } - else - { - while (n--) - { - char *c = rindex( names[n]->d_name, '.' ); - - if ( c ) - *c = '\0'; - - MESSAGE( "found instrument: %s", names[n]->d_name ); - - string s( names[n]->d_name ); - - sl->push_back( s ); - - free( names[n] ); - } - free( names ); - - return sl; - } -} - -/* Returns a list of available instruments */ -char ** -Instrument::listing ( void ) -{ - list *sys = get_listing( SYSTEM_PATH "/" INSTRUMENT_DIR ); - list *usr = get_listing( config.user_config_dir ); - - if ( ! ( usr || sys ) ) - return NULL; - - if ( sys && usr ) - usr->merge( *sys ); - else - if ( sys && ! usr ) - usr = sys; - - usr->unique(); - - usr->sort(); - - if ( sys ) - delete sys; - - char **sa = (char**)malloc( (usr->size() + 1) * sizeof( char * ) ); - - int i = 0; - for ( list ::iterator s = usr->begin(); s != usr->end(); s++, i++ ) - sa[i] = strdup( s->c_str() ); - - sa[i] = NULL; - - delete usr; - - return sa; -} - -const char * -Instrument::name ( void ) const -{ - return _name; -} diff --git a/sequencer/src/instrument.H b/sequencer/src/instrument.H deleted file mode 100644 index 350b644..0000000 --- a/sequencer/src/instrument.H +++ /dev/null @@ -1,66 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -using std::list; - -#include - -struct i_map { - char *name; - unsigned char velocity; -}; - -class Instrument -{ - - static list instruments; - - char *_name; - int _height; - mutable bool _dirty; - - struct i_map _map[128]; /* note / velocity mappings */ - - Instrument ( const char *name ); - bool read ( const char *s ); - bool write ( const char *s ) const; - -public: - - static Instrument * open ( const char *name ); - static char ** listing ( void ); - - /* mutation */ - void note ( int from, int to ); - void velocity ( int n, int v ); - void note_name ( int n, char *s ); - - /* inspection */ - bool translate ( MIDI::midievent *e ) const; - const char * note_name ( int n ) const; - int height ( void ) const; - const char * name ( void ) const; - int velocity ( int n ) const; - - void save ( void ) const; - -}; diff --git a/sequencer/src/jack.C b/sequencer/src/jack.C deleted file mode 100644 index a42d241..0000000 --- a/sequencer/src/jack.C +++ /dev/null @@ -1,640 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include -#include -/* jack */ -#include -#include -#include -#include - -#include "jack.H" -#include "non.H" -#include "transport.H" -#include "pattern.H" -#include "phrase.H" -#include -#include - -using namespace MIDI; - -#ifdef JACK_MIDI_PROTO_API -/* correct for prototype version of API */ -#define jack_midi_event_reserve( p, f, l ) jack_midi_event_reserve( p, f, l, nframes ) -#define jack_midi_event_get( e, b, f ) jack_midi_event_get( e, b, f, nframes ) -#define jack_midi_get_event_count( b ) jack_midi_get_event_count( b, nframes ) -#define jack_midi_clear_buffer( b ) jack_midi_clear_buffer( b, nframes ) -#define jack_midi_event_write( b, f, d, s ) jack_midi_event_write( b, f, d, s, nframes ) -#endif - - -/* MIDI channel to listen for pattern control changes on */ -int pattern_control_channel = 0; - -/* which control change number to use for pattern control */ -int pattern_control_cc = 20; - -jack_client_t *client; - -int sample_rate; - -const int MAX_PORT = 16; - -const int subticks_per_tick = 4096; - -/* timers for notes on all channels and ports. When a note is played, - * the respective value in this array is set to the note duraction in - * subticks (an arbitrary division of the tick used only for this - * purpose). Decremented in each process cycle, when this value - * reaches zero, a note off is generated--regardless of the state of - * the transport */ -int note_duration[MAX_PORT][16][128]; - -/* tracks the number of concurrent note ons for the same note so that - * we can be sure to emit the correct number of note offs */ -int notes_on[MAX_PORT][16][128]; - -typedef unsigned char byte_t; - -int num_output_ports = 1; - -event_list freelist; - -typedef struct { - void *buf; - jack_ringbuffer_t *ring_buf; /* for realtime output and recording */ - event_list events; /* events to be output this cycle */ - jack_port_t *port; -} port_t; - -static port_t output[MAX_PORT]; -static port_t input[2]; /* control, performance */ - -jack_nframes_t nframes; /* for compatibility with older jack */ - -bool -midi_is_active ( void ) -{ - return client != NULL; -} - -/** get next recorded event, if any--runs in UI thread */ -bool -midi_input_event ( int port, midievent *me ) -{ - if ( ! midi_is_active() ) - return NULL; - - if ( jack_ringbuffer_read_space( input[ port ].ring_buf ) >= sizeof( midievent ) ) - { - if ( jack_ringbuffer_read( input[ port ].ring_buf, (char *)me, sizeof( midievent ) ) ) - return true; - } - return false; -} - - -/** - * Queue an event for output. /tick/ is relative to the current cycle! */ -void -midi_output_event ( int port, const midievent *e ) -{ - if ( ! midi_is_active() ) - return; - - event *fe = freelist.first(); - - if ( ! fe ) - { - WARNING( "output buffer underrun" ); - } - else - { - if ( e->is_note_on() ) - { - if ( notes_on[ port ][ e->channel() ][ e->note() ] == 0 ) - { - freelist.unlink( fe ); - *fe = *e; - - output[ port ].events.insert( fe ); - ++notes_on[ port ][ e->channel() ][ e->note() ]; - } - else - { - DMESSAGE( "Dropping extra Note ON" ); - } - } - else if ( e->is_note_off() ) - { - if ( notes_on[ port ][ e->channel() ][ e->note() ] == 0 ) - { - DMESSAGE( "Dropping extra Note OFF" ); - } - else - { - freelist.unlink( fe ); - *fe = *e; - - output[ port ].events.insert( fe ); - --notes_on[ port ][ e->channel() ][ e->note() ]; - } - } - else - { - freelist.unlink( fe ); - *fe = *e; - - output[ port ].events.insert( fe ); - } - } -} - -/** same as above, but only for note-on + duration */ -void -midi_output_event ( int port, const midievent *e, tick_t duration ) -{ - if ( ! midi_is_active() ) - return; - - if ( duration ) - { - note_duration[ port ][ e->channel() ][ e->note() ] = (duration + e->timestamp()) * subticks_per_tick; - midi_output_event( port, e ); - } - else - { - /* We allow duplicate notes on and pass notes off through as - * is in order to support poly synths. */ - midi_output_event( port, e ); - } -} - -void -midi_write_event ( int port, const midievent *e ) -{ - byte_t *buffer; - - // what I want here is to translate a PPQN tick into the - // current period. - jack_nframes_t frame = transport.frames_per_tick * e->timestamp(); - - int l = e->size(); - - buffer = jack_midi_event_reserve( output[ port ].buf, frame, l ); - - if ( ! buffer ) - { - WARNING( "could not reserve buffer at frame %d, note event dropped!", frame ); - return; - } - -#ifdef DEBUG_EVENTS - e->pretty_print(); -#endif - - e->raw( buffer, l ); -} - - -/** Call this to send an event immediately from UI thread. Timestamp is meaningless */ -void -midi_output_immediate_event ( int port, const midievent *e ) -{ - if ( ! midi_is_active() ) - return; - - if ( jack_ringbuffer_write( output[ port ].ring_buf, (const char *)e, sizeof( midievent ) ) != sizeof( midievent ) ) - WARNING( "output ringbuffer overrun" ); - else - if ( e->is_note_on() ) - { - /* use timestamp as duration */ - note_duration[ port ][ e->channel() ][ e->note() ] = e->timestamp() * subticks_per_tick; - } -} - -/** stop all notes on all channels of all ports */ -void -midi_all_sound_off ( void ) -{ - if ( ! midi_is_active() ) - return; - - MESSAGE( "stopping all sound" ); - - midievent e; - - /* all notes off */ - e.status( midievent::CONTROL_CHANGE ); - e.data( 123, 0 ); - e.timestamp( 0 ); - - for ( int p = MAX_PORT; p--; ) - for ( int c = 16; c--; ) - { - e.channel( c ); - midi_output_immediate_event( p, &e ); - } -} - -static void -stop_all_patterns ( void ) -{ - for ( uint i = pattern::patterns(); i--; ) - { - pattern *p = pattern::pattern_by_number( i + 1 ); - - p->stop(); - } -} - -static int -sync ( jack_transport_state_t state, jack_position_t *pos, void * ) -{ - switch ( state ) - { - case JackTransportStopped: /* new position requested */ - /* JACK docs lie. This is only called when the transport - is *really* stopped, not when starting a slow-sync - cycle */ - stop_all_patterns(); - return 1; - case JackTransportStarting: /* this means JACK is polling slow-sync clients */ - { - stop_all_patterns(); - return 1; - } - case JackTransportRolling: /* JACK's timeout has expired */ - /* FIXME: what's the right thing to do here? */ -// request_locate( pos->frame ); - return 1; - break; - default: - WARNING( "unknown transport state" ); - } - - return 0; -} - - -static int -process ( jack_nframes_t nframes, void *arg ) -{ - static tick_t oph = 0; - static int old_play_mode = PATTERN; - - static int not_dropped = 0; - - ::nframes = nframes; - - transport.nframes = nframes; - transport.poll(); - - /* ph-nph is exclusive. It is important that in normal continuous playback each tick is covered exactly once! */ - const tick_t ph = transport.ticks; - const tick_t nph = transport.ticks + transport.ticks_per_period; - - if ( ! transport.valid ) - goto schedule; - - if ( ( ! transport.rolling ) || ph == oph ) - goto schedule; - - /* if ( ph != onph ) */ - /* { */ - /* if ( onph > ph ) */ - /* DWARNING( "duplicated %lu ticks (out of %d)", onph - ph, (int)(not_dropped * transport.ticks_per_period) ); */ - /* else */ - /* DWARNING( "dropped %lu ticks (out of %d), ticks per period = %f", ph - onph, (int)(not_dropped * transport.ticks_per_period) ); */ - - /* not_dropped = 0; */ - /* } */ - - ++not_dropped; - -// onph = nph; - - if ( old_play_mode != song.play_mode ) - { - switch ( old_play_mode ) - { - case PATTERN: - case TRIGGER: - case QUEUE: - DMESSAGE( "Stopping all patterns" ); - stop_all_patterns(); - break; - } - old_play_mode = song.play_mode; - } - -// DMESSAGE( "tpp %f %lu-%lu", transport.ticks_per_period, ph, nph ); - - /* now handle control input */ - { - int j = CONTROL; - - static midievent e; - - input[j].buf = jack_port_get_buffer( input[j].port, nframes ); - - jack_midi_event_t ev; - - jack_nframes_t count = jack_midi_get_event_count( input[j].buf ); - - for ( uint i = 0; i < count; ++i ) - { -// MESSAGE( "Got midi input!" ); - - jack_midi_event_get( &ev, input[j].buf, i ); - - /* time is frame within cycle, convert to absolute tick */ - e.timestamp( ph + (ev.time / transport.frames_per_tick) ); - e.status( ev.buffer[0] ); - e.lsb( ev.buffer[1] ); - if ( ev.size == 3 ) - e.msb( ev.buffer[2] ); - - /* no need to pass it to the GUI, we can trigger patterns here */ - - if ( e.channel() == pattern_control_channel && - e.opcode() == midievent::CONTROL_CHANGE && - e.lsb() == pattern_control_cc ) - { - if ( e.msb() < pattern::patterns() ) - { - - pattern *p = pattern::pattern_by_number( e.msb() + 1 ); - - if ( TRIGGER == song.play_mode ) - { - if ( p->playing() ) - { - DMESSAGE( "Untriggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); - - p->trigger( ph, e.timestamp() ); - } - else - { - DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); - - p->trigger( e.timestamp(), INFINITY ); - } - } - else - { - if ( p->mode() == PLAY ) - { - DMESSAGE( "Dequeuing pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); - p->mode( MUTE ); - } - else - { - DMESSAGE( "Queuing pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); - - p->mode( PLAY ); - } - } - } - } - } - } - - - switch ( song.play_mode ) - { - case SEQUENCE: - playlist->play( ph, nph ); - break; - case QUEUE: - case PATTERN: - { - for ( uint i = pattern::patterns(); i--; ) - { - pattern *p = pattern::pattern_by_number( i + 1 ); - - p->trigger( 0, INFINITY ); - - p->play( ph, nph ); - } - break; - } - case TRIGGER: - { - for ( uint i = pattern::patterns(); i--; ) - { - pattern *p = pattern::pattern_by_number( i + 1 ); - - p->play( ph, nph ); - } - break; - } - } - - oph = ph; - - /* handle midi input */ -// for ( int j = transport.recording ? 2 : 1; j--; ) - - if ( transport.recording ) - { - int j = PERFORMANCE; - - static midievent e; - - input[j].buf = jack_port_get_buffer( input[j].port, nframes ); - - jack_midi_event_t ev; - - jack_nframes_t count = jack_midi_get_event_count( input[j].buf ); - - for ( uint i = 0; i < count; ++i ) - { -// MESSAGE( "Got midi input!" ); - - jack_midi_event_get( &ev, input[j].buf, i ); - - /* time is frame within cycle, convert to absolute tick */ - e.timestamp( ph + (ev.time / transport.frames_per_tick) ); - e.status( ev.buffer[0] ); - e.lsb( ev.buffer[1] ); - if ( ev.size == 3 ) - e.msb( ev.buffer[2] ); - - if ( jack_ringbuffer_write( input[j].ring_buf, (char*)&e, sizeof( midievent ) ) != sizeof( midievent ) ) - WARNING( "input buffer overrun" ); - } - } - - -schedule: - - const int subticks_per_period = transport.ticks_per_period * subticks_per_tick; - - for ( uint i = MAX_PORT; i-- ; ) - { - /* reserve and clear buffers */ - output[ i ].buf = jack_port_get_buffer( output[ i ].port, nframes ); - jack_midi_clear_buffer( output[ i ].buf ); - - /* handle scheduled note offs */ - for ( uint j = 16; j-- ; ) - { - register int *note = ¬e_duration[ i ][ j ][ 0 ]; - - for ( register uint k = 0; k < 128; ++note, ++k ) - if ( *note > 0 ) - if ( ( *note -= subticks_per_period ) <= 0 ) - { - while ( notes_on[ i ][ j ][ k] > 0 ) - { - static midievent e; - - e.status( midievent::NOTE_OFF ); - e.channel( j ); - e.note( k ); - e.note_velocity( 64 ); - - e.timestamp( (subticks_per_period + *note) / subticks_per_tick ); - - midi_output_event( i, &e ); - } - - *note = 0; - } - } - - - static midievent e; - /* first, write any immediate events from the UI thread */ - while ( jack_ringbuffer_read( output[ i ].ring_buf, (char *)&e, sizeof( midievent ) ) ) - { -// MESSAGE( "sending immediate event" ); - // FIXME: could we do better? - e.timestamp( 0 ); - - midi_output_event( i, &e ); - } - - /* Write queued events */ - event *n; - for ( event *e = output[ i ].events.first(); e; e = n ) - { - n = e->next(); - - midi_write_event( i, e ); - - output[ i ].events.unlink( e ); - - freelist.append( e ); - } - } - - return 0; -} - -const char * -midi_init ( const char *name ) -{ - MESSAGE( "Initializing Jack MIDI" ); - - if (( client = jack_client_open ( name, (jack_options_t)0, NULL )) == 0 ) - return NULL; - - /* create output ports */ - for ( int i = 0; i < MAX_PORT; i++ ) - { - char pat[40]; - - sprintf( pat, "midi_out-%d", i + 1 ); - output[i].port = jack_port_register( client, pat, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - output[i].ring_buf = jack_ringbuffer_create( 16 * 16 * sizeof( midievent ) ); // why this value? - jack_ringbuffer_reset( output[i].ring_buf ); - - } - - /* create input ports */ - input[0].port = jack_port_register( client, "control_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - input[0].ring_buf = jack_ringbuffer_create( 128 * sizeof( midievent ) ); // why this value? - jack_ringbuffer_reset( input[0].ring_buf ); - input[1].port = jack_port_register( client, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - input[1].ring_buf = jack_ringbuffer_create( 128 * sizeof( midievent ) ); // why this value? - jack_ringbuffer_reset( input[1].ring_buf ); - - /* preallocate events */ - for ( int i = 32 * 16 * MAX_PORT; i-- ; ) - freelist.append( new event ); - - DMESSAGE( "allocated output buffer space for %lu events", freelist.size() ); - - /* clear notes */ - for ( int p = MAX_PORT; p--; ) - { - for ( int c = 16; c-- ; ) - for ( int n = 128; n-- ; ) - { - note_duration[ p ][ c ][ n ] = 0; - notes_on[ p ][ c ][ n ] = 0; - } - } - -//1 jack_set_buffer_size_callback( client, bufsize, 0 ); - jack_set_process_callback( client, process, 0 ); - jack_set_sync_callback( client, sync, 0 ); - -/* /\* initialize buffer size *\/ */ -/* transport_poll(); */ -/* bufsize( jack_get_buffer_size( client ), 0 ); */ - - if ( jack_set_timebase_callback( client, 1, Transport::timebase, NULL ) == 0 ) - { - MESSAGE( "running as timebase master" ); - transport.master = true; - } - else - WARNING( "could not take over as timebase master" ); - - jack_activate( client ); - - sample_rate = jack_get_sample_rate( client ); - - /* FIXME: hack! we need to wait until jack finally calls our - * timebase and process callbacks in order to be able to test for - * valid transport info. */ - MESSAGE( "Waiting for JACK..." ); - usleep( 500000 ); - - return (const char *) jack_get_client_name(client); -} - -void -midi_shutdown ( void ) -{ - // TODO: wait for all queued events to play. - if ( client ) - { - jack_deactivate( client ); - jack_client_close( client ); - client = NULL; - } -} diff --git a/sequencer/src/jack.H b/sequencer/src/jack.H deleted file mode 100644 index 7d6ed99..0000000 --- a/sequencer/src/jack.H +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include -#include "common.h" - -enum { CONTROL, PERFORMANCE }; - - -bool midi_input_event ( int port, MIDI::midievent *e ); -bool midi_is_active ( void ); -MIDI::midievent * midi_input_event ( int port ); -void midi_output_event ( int port, const MIDI::midievent *e ); -void midi_output_event ( int port, const MIDI::midievent *e, tick_t duration ); -void midi_all_sound_off ( void ); -const char * midi_init ( const char *name ); -void midi_shutdown ( void ); -void midi_output_immediate_event ( int port, const MIDI::midievent *e ); diff --git a/sequencer/src/main.C b/sequencer/src/main.C deleted file mode 100644 index a89cd96..0000000 --- a/sequencer/src/main.C +++ /dev/null @@ -1,292 +0,0 @@ -/**********************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ; */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software ; */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/**********************************************************************************/ - -#include -#include -#include -#include - -#include "non.H" -// #include "gui/input.H" -#include "gui/ui.H" -#include "jack.H" -#include "NSM.H" -#include "transport.H" -#include "pattern.H" -#include "phrase.H" -#include -#include -using namespace MIDI; - -// extern const char *BUILD_ID; -// extern const char *VERSION; - -const double NSM_CHECK_INTERVAL = 0.25f; - -sequence *playlist; - -global_settings config; -song_settings song; - -NSM_Client *nsm; - -char *instance_name; - -/* default to pattern mode */ - -UI *ui; - -void -quit ( void ) -{ - /* clean up, only for valgrind's sake */ - ui->save_settings(); - - delete ui; - - midi_all_sound_off(); - - // wait for it... - sleep( 1 ); - - midi_shutdown(); - - - MESSAGE( "Your fun is over" ); - - exit( 0 ); -} - -void -clear_song ( void ) -{ -// song.filename = NULL; - - ui->pattern_canvas_widget->grid( NULL ); - ui->phrase_canvas_widget->grid( NULL ); - - playlist->reset(); - playlist->insert( 0, 1 ); - - ui->pattern_canvas_widget->grid( new pattern ); - ui->phrase_canvas_widget->grid( new phrase ); - - song.dirty( false ); -} - -void -init_song ( void ) -{ - if ( ! midi_is_active() ) - setup_jack(); - - if ( !( nsm && nsm->is_active() ) ) - song.filename = NULL; - - clear_song(); - - if ( nsm && nsm->is_active() ) - save_song( song.filename ); -} - -void -handle_midi_input ( void ) -{ - midievent e; - while ( ( midi_input_event( PERFORMANCE, &e ) ) ) - { - pattern::record_event( &e ); - } -} - -bool -load_song ( const char *name ) -{ - if ( ! midi_is_active() ) - setup_jack(); - - MESSAGE( "loading song \"%s\"", name ); - - Grid *pattern_grid = ui->pattern_canvas_widget->grid(); - Grid *phrase_grid = ui->phrase_canvas_widget->grid(); - - ui->pattern_canvas_widget->grid( NULL ); - ui->phrase_canvas_widget->grid( NULL ); - - if ( ! playlist->load( name ) ) - { - WARNING( "failed to load song file" ); - goto failed; - } - - ui->pattern_canvas_widget->grid( pattern::pattern_by_number( 1 ) ); - ui->phrase_canvas_widget->grid( phrase::phrase_by_number( 1 ) ); - - song.filename = strdup( name ); - - song.dirty( false ); - - return true; - -failed: - - ui->pattern_canvas_widget->grid( pattern_grid ); - ui->phrase_canvas_widget->grid( phrase_grid ); - - return false; -} - -bool -save_song ( const char *name ) -{ - playlist->save( name ); - - song.filename = strdup( name ); - song.dirty( false ); - - return true; -} - - -void -setup_jack ( ) -{ - const char *jack_name; - - jack_name = midi_init( instance_name ); - if ( ! jack_name ) - ASSERTION( "Could not initialize MIDI system! (is Jack running and with MIDI ports enabled?)" ); - - if ( ! transport.valid ) - { - if ( transport.master ) - ASSERTION( "The version of JACK you are using does not appear to be capable of passing BBT positional information." ); - else - ASSERTION( "Either the version of JACK you are using does pass BBT information, or the current timebase master does not provide it." ); - } -} - -static int got_sigterm = 0; - -void -sigterm_handler ( int ) -{ - got_sigterm = 1; - Fl::awake(); -} - -void -check_sigterm ( void * ) -{ - if ( got_sigterm ) - { - MESSAGE( "Got SIGTERM, quitting..." ); - quit(); - } -} - - -void -check_nsm ( void * v ) -{ - nsm->check(); - Fl::repeat_timeout( NSM_CHECK_INTERVAL, check_nsm, v ); -} - -int -main ( int argc, char **argv ) -{ - - printf( "%s %s %s -- %s\n", APP_TITLE, VERSION, "", COPYRIGHT ); - - if ( ! Fl::visual( FL_DOUBLE | FL_RGB ) ) - { - WARNING( "Xdbe not supported, FLTK will fake double buffering." ); - } - - ::signal( SIGTERM, sigterm_handler ); - ::signal( SIGHUP, sigterm_handler ); - ::signal( SIGINT, sigterm_handler ); - - config.follow_playhead = true; - config.record_mode = MERGE; - song.play_mode = PATTERN; - - asprintf( &config.user_config_dir, "%s/%s", getenv( "HOME" ), USER_CONFIG_DIR ); - mkdir( config.user_config_dir, 0777 ); - - playlist = new sequence; - - nsm = new NSM_Client; - - song.filename = NULL; - - ui = new UI; - - pattern::signal_create_destroy.connect( mem_fun( ui->phrase_canvas_widget, &Canvas::v_zoom_fit ) ); - pattern::signal_create_destroy.connect( mem_fun( song, &song_settings::set_dirty ) ); - phrase::signal_create_destroy.connect( mem_fun( song, &song_settings::set_dirty ) ); - - song.dirty( false ); - - clear_song(); - -#ifdef HAVE_XPM - ui->main_window->icon((char *)p); -#endif - ui->main_window->show( 0, 0 ); - - instance_name = strdup( APP_NAME ); - - const char *nsm_url = getenv( "NSM_URL" ); - - if ( nsm_url ) - { - if ( ! nsm->init( nsm_url ) ) - { - nsm->announce( APP_NAME, ":switch:dirty:", argv[0] ); - - song.signal_dirty.connect( sigc::mem_fun( nsm, &NSM_Client::is_dirty ) ); - song.signal_clean.connect( sigc::mem_fun( nsm, &NSM_Client::is_clean ) ); - - // poll so we can keep OSC handlers running in the GUI thread and avoid extra sync - Fl::add_timeout( NSM_CHECK_INTERVAL, check_nsm, NULL ); - } - else - WARNING( "Error initializing NSM" ); - } - else - { - setup_jack(); - if ( argc > 1 ) - { - /* maybe a filename on the commandline */ - if ( ! load_song( argv[ 1 ] ) ) - ASSERTION( "Could not load song \"%s\" specified on command line", argv[ 1 ] ); - } - } - - MESSAGE( "Initializing GUI" ); - - Fl::add_check( check_sigterm ); - - ui->load_settings(); - ui->run(); - - return 0; -} diff --git a/sequencer/src/mapping.C b/sequencer/src/mapping.C deleted file mode 100644 index 47c9b8e..0000000 --- a/sequencer/src/mapping.C +++ /dev/null @@ -1,170 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "mapping.H" -#include "stdlib.h" -#include "common.h" -#include - -using namespace MIDI; -/* Is C++'s dispatching useless or what? */ - -#define IS_INSTRUMENT ( _type == INSTRUMENT ) - -Mapping::Mapping ( ) -{ - _key = 0; - _type = NONE; -} - -bool -Mapping::open ( enum map_type type, const char *name ) -{ - switch ( type ) - { - case INSTRUMENT: - _instrument = Instrument::open( name ); - break; - case SCALE: - _scale = Scale::open( name ); - break; - default: - ASSERTION( "invalid mapping type "); - break; - } - - if ( ! _scale ) - return false; - - _type = type; - - return true; -} - -Mapping::Mapping ( const Mapping &rhs ) -{ - _key = rhs._key; - _type = rhs._type; - _instrument = rhs._instrument; -} - -const char * -Mapping::name ( void ) const -{ - switch ( _type ) - { - case INSTRUMENT: - return _instrument->name(); - case SCALE: - return _scale->name(); - } - - return NULL; -} - - -int -Mapping::height ( void ) const -{ - if ( IS_INSTRUMENT ) - return _instrument->height(); - else - return 0; -} - -void -Mapping::key ( int n ) -{ - if ( n > 11 || n < 0 ) - ASSERTION( "key selection out of range: %d", n ); - - _key = n; -} - -int -Mapping::key ( void ) const -{ - return _type == INSTRUMENT ? -1 : _key; -} - -bool -Mapping::translate ( midievent *e ) const -{ - switch ( _type ) - { - case INSTRUMENT: - return _instrument->translate( e ); - case SCALE: - return _scale->translate( _key, e ); - } - - return false; -} - -int -Mapping::velocity ( int n ) const -{ - switch ( _type ) - { - case INSTRUMENT: - return _instrument->velocity( n ); - case SCALE: - return 0; - } - - return 0; -} - -const char * -Mapping::note_name ( int n ) const -{ - switch ( _type ) - { - case INSTRUMENT: - return _instrument->note_name( n ); - case SCALE: - return _scale->note_name( _key, n ); - } - - return NULL; -} - -/* For the instrument editor... */ -Instrument * -Mapping::instrument ( void ) const -{ - if ( IS_INSTRUMENT ) - return _instrument; - else - return NULL; -} - -/** return a string describing the type of this mapping */ -const char * -Mapping::type ( void ) const -{ - return IS_INSTRUMENT ? "Instrument" : "Scale"; -} - - -bool -Mapping::editable ( void ) const -{ - return IS_INSTRUMENT ? true : false; -} diff --git a/sequencer/src/mapping.H b/sequencer/src/mapping.H deleted file mode 100644 index e00cece..0000000 --- a/sequencer/src/mapping.H +++ /dev/null @@ -1,76 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "scale.H" -#include "instrument.H" -#include - -/* C++'s inheritance system falls down dead for this application, so we - have to do it backwards, using the base class (Mapping) as an interface - to Instrument and Scale */ - - -class Mapping -{ - -public: - - enum map_type { NONE, INSTRUMENT, SCALE }; - -private: - - union { - Instrument *_instrument; - Scale *_scale; - }; - - int _key; /* used for scales, 0 == A */ - - int _type; - -public: - - Mapping ( ); - Mapping ( const Mapping &rhs ); - - bool open ( map_type type, const char *name ); - - const char * name ( void ) const; - int height ( void ) const; - - Instrument * instrument ( void ) const; - - /* mutation */ - void note ( int from, int to ); - void velocity ( int n, int v ); - void note_name ( int n, char *s ); - void key ( int n ); - - /* inspection */ - bool translate ( MIDI::midievent *e ) const; - const char * note_name ( int n ) const; - int velocity ( int n ) const; - int key ( void ) const; - bool editable ( void ) const; - - const char * type ( void ) const; - -}; diff --git a/sequencer/src/non.H b/sequencer/src/non.H deleted file mode 100644 index 98453be..0000000 --- a/sequencer/src/non.H +++ /dev/null @@ -1,127 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "common.h" -#include "pattern.H" -#include "phrase.H" -#include "sequence.H" - -enum { - PLAY, - MUTE, - SOLO -}; - -class Canvas; -class Lash; - -extern Canvas *pattern_c, *phrase_c; -extern sequence *playlist; -extern Lash lash; - -void quit ( void ); -void init_song ( void ); -void handle_midi_input ( void ); -bool load_song ( const char *name ); -bool save_song ( const char *name ); -void setup_jack ( void ); - -#include "common.h" -#include "const.h" - - -enum play_mode_e { - PATTERN, - SEQUENCE, - TRIGGER, - QUEUE -// PHRASE, -}; - - -enum record_mode_e { - MERGE, - OVERWRITE, - LAYER, - NEW -}; - - -/* program settings (from rc file) */ -struct global_settings { - - enum record_mode_e record_mode; - - bool record_filtered; /* ignore non-note events while recording */ - bool visual_metronome; /* show visual metronome */ - bool follow_playhead; - - char *user_config_dir; - -}; -extern global_settings config; - -/* song settings (from song file) */ -struct song_settings -{ - - enum play_mode_e play_mode; - - char *filename; - - signal signal_dirty; /* emitted when first dirtied */ - signal signal_clean; /* emitted when first cleaned */ - - bool _dirty; - - bool dirty ( void ) - { - return _dirty; - } - - void - dirty( bool b ) - { - if ( _dirty != b ) - { - _dirty = b; - - if ( b ) - { - DMESSAGE( "song is now dirty" ); - signal_dirty(); - } - else - { - DMESSAGE( "song is now clean" ); - signal_clean(); - } - } - } - - void - set_dirty ( void ) - { - dirty( true ); - } - -}; -extern song_settings song; diff --git a/sequencer/src/pattern.C b/sequencer/src/pattern.C deleted file mode 100644 index c21f7d9..0000000 --- a/sequencer/src/pattern.C +++ /dev/null @@ -1,739 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "pattern.H" -#include "non.H" -#include "common.h" -#include "smf.H" - -#include "jack.H" -#include "transport.H" -#include - -#include -using namespace MIDI; - -event_list pattern::_recorded_events; -vector pattern::_patterns; -int pattern::_solo; -int pattern::_pattern_recording; - -signal pattern::signal_create_destroy; - -pattern::pattern ( void ) -{ - viewport.h = 32; - viewport.w = 32; - - viewport.y = 64 - ( viewport.h + ( viewport.h / 2 ) ); - - _channel = _port = 0; - - _ppqn = 4; - _bpb = 4; - _note = 8; - - _queued = -1; - - int _bars = 2; - - // we need to reinitalize this. - data *d = const_cast< data * >( _rd ); - - d->length = x_to_ts( _bpb * _ppqn * _bars ); - -// mapping.open( Mapping::INSTRUMENT, "Default" ); - mapping.open( Mapping::SCALE, "Major" ); - - _add(); - - char *s; - asprintf( &s, "Pattern %d", number() ); - - name( s ); -} - -void -pattern::_add ( void ) -{ - // keep track of all the patterns - pattern::_patterns.push_back( this ); - _number = patterns(); - - signal_create_destroy(); -} - -pattern::~pattern ( void ) -{ - DMESSAGE( "deleting pattern %d", number() ); - signal_create_destroy(); -} - -/* copy constructor */ -pattern::pattern ( const pattern &rhs ) : Grid( rhs ) -{ - _note = rhs._note; - _port = rhs._port; - _channel = rhs._channel; - _queued = rhs._queued; - - mapping = rhs.mapping; - - _add(); -} - -pattern * -pattern::clone ( void ) -{ - return new pattern( *this ); -} - -/******************/ -/* Static methods */ -/******************/ - -int -pattern::solo ( void ) -{ - return pattern::_solo; -} - -int -pattern::patterns ( void ) -{ - return pattern::_patterns.size(); -} - -// this is the static one -pattern * -pattern::pattern_by_number ( int n ) -{ - if ( n <= patterns() && n > 0 ) - { - return pattern::_patterns[ n - 1 ]; - } - return NULL; -} - -/** delete all patterns in preparation for a reload */ -void -pattern::reset ( void ) -{ - for ( int n = pattern::patterns(); n-- ; ) - { - delete pattern::_patterns.back(); - pattern::_patterns.pop_back(); - } -} - -/* runs in the UI thread */ -/* records a MIDI event into a temporary buffer. It'll only be - * permanently added to pattern after recording stops or the pattern - * loops. */ -void -pattern::record_event ( const midievent *me ) -{ - /* set the events aside in a dedicated list--the recording pattern - * will decide what to do with them the next time around the - * loop */ - - /* FIXME: how does the pattern decide when to loop? It seems - reasonable that /merge/ and /replace/ modes should be bound to - the previous pattern length, but what about "NEW" mode? Should it - just use this entire list as a new pattern (of whatever length) - when recording is halted? */ - - event *e = new event; - - *e = *me; - - pattern::_recorded_events.append( e ); - - record_mode_e mode = config.record_mode; - - if ( mode == OVERWRITE || mode == LAYER ) - { - pattern *p = pattern::recording(); - - if ( ! p->_cleared ) - { - - if ( mode == LAYER ) - { - p->record_stop(); - - p = p->clone(); - - p->record( 0 ); - } - - p->clear(); - - p->_cleared = true; - } - - mode = MERGE; - } - - /* let's fill in the pattern 'live' in merge mode. looks a little - complicated because we have to wait for a note-off before it's - safe to insert */ - if ( mode == MERGE || mode == NEW ) - { - - pattern *p = pattern::recording(); - - p->lock(); - - event_list *el = &pattern::_recorded_events; - - if ( e->is_note_off() ) - { - event *off = e; - - for ( event *on = el->last(); on; on = on->prev() ) - { - if ( on->is_note_on() && - on->is_same_note( off ) ) - // && - // *on < *e ) - { - el->unlink( on ); - el->unlink( off ); - - tick_t duration = off->timestamp() - on->timestamp(); - - /* place within loop */ - on->timestamp( - fmod( on->timestamp() - p->_start, p->_rw->length ) ); - - on->link( off ); - on->note_duration( duration ); - - p->_rw->events.mix( on ); - - break; - } - } - } - else - if ( ! e->is_note_on() ) - { - - // if ( ! filter ) - - e->timestamp( fmod( e->timestamp(), p->_rw->length ) ); - - el->unlink( e ); - p->_rw->events.insert( e ); - } - - p->unlock(); - } -} - -pattern * -pattern::recording ( void ) -{ - return pattern::pattern_by_number( pattern::_pattern_recording ); -} - - - -/*******************/ -/* Virtual Methods */ -/*******************/ - -/* allows us to create a new pattern/phrase from a base class pointer */ -pattern * -pattern::create ( void ) -{ - if ( pattern::patterns() < 128 ) - { - return new pattern; - } - else - return NULL; -} - -pattern * -pattern::by_number ( int n ) const -{ - return pattern::pattern_by_number( n ); -} - -/** what to do when the row name is pressed */ -void -pattern::row_name_press ( int y ) -{ - /* echo note */ - midievent e; - - e.status( event::NOTE_ON ); - e.channel( _channel ); - e.timestamp( default_length() ); - e.note( y ); - e.note_velocity( 64 ); - - midi_output_immediate_event ( _port, &e ); -} - -void -pattern::put ( int x, int y, tick_t l ) -{ - l = l ? l : default_length(); - - Grid::put( x, y, l ); - - if ( ! transport.rolling ) - { - /* echo note */ - midievent e; - - e.status( event::NOTE_ON ); - e.channel( _channel ); - e.timestamp( l ); - e.note( y_to_note( y ) ); - e.note_velocity( 64 ); - - midi_output_immediate_event ( _port, &e ); - } -} - -const char * -pattern::row_name ( int r ) const -{ - return mapping.note_name( y_to_note( r ) ); -} - -void -pattern::draw_row_names ( Canvas *c ) const -{ - for ( int y = 128; y-- ; ) - c->draw_row_name( y, mapping.note_name( y_to_note( y ) ), mapping.velocity( y_to_note( y ) ) ); -} - -void -pattern::trigger ( tick_t start, tick_t end ) -{ - /* ASSERT( end != -1 && start <= end, "programming error: invalid loop trigger! (%lu-%lu)", start, end ); */ - - _start = start; - _end = end; -} - -/* trigger forever */ -void -pattern::trigger ( void ) -{ - trigger( transport.frame / transport.frames_per_tick, INFINITY ); -} - -void -pattern::stop ( void ) const -{ - _playing = false; - - _start = 0; - _end = 0; - _index = 0; -} - - -void -pattern::mode ( int n ) -{ - if ( QUEUE == song.play_mode ) - { - queue( n ); - return; - } - - if ( n == SOLO ) - { - if ( pattern::_solo ) - ((Grid*)pattern::pattern_by_number( pattern::_solo ))->mode( PLAY ); - pattern::_solo = _number; - Grid::mode( SOLO ); - } - else - { - if ( pattern::_solo == _number ) - pattern::_solo = 0; - - Grid::mode( n ); - } -} - -int -pattern::mode ( void ) const -{ - if ( pattern::_solo ) - { - if ( pattern::_solo == _number ) - return SOLO; - else - return MUTE; - } - else - return Grid::mode(); -} - -/* queue a mode change for the next loop */ -void -pattern::queue ( int m ) -{ - _queued = m; -} - -int -pattern::queue ( void ) const -{ - return _queued; -} - -/* WARNING: runs in the RT thread! */ -// output notes from /start/ to /end/ (absolute) -void -pattern::play ( tick_t start, tick_t end ) const -{ - /* get our own copy of this pointer so UI thread can change it. */ - const data *d = const_cast< const data * >(_rd); - - if ( start > _end ) - { - stop(); -// WARNING( "attempt to play a loop (pattern %d) that has ended (%lu, %lu)", number(), start, _end ); - return; - } - else - if ( end < _start ) - // not ready yet - return; - - if ( start < _start ) - start = _start; - - if ( end > _end ) - end = _end; - - // where we are in the absolute time - tick_t tick = start - _start; - int num_played = tick / d->length; - tick_t offset = _start + (d->length * num_played); - - const event *e; - - _index = fmod( tick, d->length ); - - bool reset_queued = false; - - if ( _index < end - start ) - { - /* period covers the beginning of the loop */ - DMESSAGE( "%s pattern %d at tick %f (ls: %f, le: %f, o: %f)", _playing ? "Looped" : "Triggered", number(), start, _start, _end, offset ); - - _cleared = false; - - if ( PLAY == _queued || SOLO == _queued ) - { - /* set the start point to loop boundary */ - start = start - _index; - _mode = _queued; - - if ( SOLO == _mode ) - { - if ( pattern::_solo ) - ((Grid*)pattern::pattern_by_number( pattern::_solo ))->mode( PLAY ); - - pattern::_solo = _number; - } - else - { - if ( pattern::_solo == _number ) - pattern::_solo = 0; - } - - reset_queued = true; - } - } - else if ( _index >= d->length - ( end - start ) ) - { - if ( MUTE == _queued ) - { - /* set the end point to loop boundary */ - end = end - _index; - - reset_queued = true; - } - } - - _playing = true; - - if ( mode() == MUTE ) - goto done; - -try_again: - - // pattern is empty - if ( d->events.empty() ) - goto done; - - for ( e = d->events.first(); e; e = e->next() ) - { - // MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print(); - - tick_t ts = e->timestamp() + offset; - - if ( ts >= end ) - goto done; - - if ( ts >= start ) - { - midievent me = *e; - - - // MESSAGE( "timestamp %d, tick %d, ts - start == %lu", e->timestamp(), start, - // e->timestamp() - start); - - /* set the channel */ - me.channel( _channel ); - - /* set the in-cycle timestamp */ - me.timestamp ( ts - start ); - - if ( me.is_note_on() ) - { - if ( mapping.translate( &me ) ) - midi_output_event( _port, &me, 1 + e->note_duration() ); - } - else - if ( me.is_note_off() ) - { - if ( mapping.translate( &me ) ) - midi_output_event( _port, &me, 0 ); - } - else - /* any other event type */ - midi_output_event( _port, &me ); - } - } - - // ran out of events, but there's still some loop left to play. - offset += d->length; - goto try_again; - - DMESSAGE( "out of events, resetting to satisfy loop" ); - -done: - - if ( _queued >= 0 && reset_queued ) - { - _mode = _queued; - _queued = -1; - } - - if ( _end == end ) - { - /* we're done playing this trigger */ - DMESSAGE( "Pattern %d ended at tick %f (ls: %f, le: %f, o: %f)", number(), end, _start, _end, offset ); - - stop(); - } - -} - -/* Import /track/ of /f/ as new pattern */ -pattern * -pattern::import ( smf *f, int track ) -{ - if ( ! f->seek_track( track ) ) - return NULL; - - pattern *p = new pattern; - - p->lock(); - - p->load( f ); - - /* file could have any notes in it... Use Chromatic scale to - ensure all are visible */ - p->mapping.open( Mapping::SCALE, "Chromatic" ); - - p->unlock(); - - p->fit(); - - return p; -} - -/** fill pattern from current track of /f/ */ -void -pattern::load ( smf *f ) -{ - lock(); - - f->read_pattern_info( this ); - - tick_t len; - - list *e = f->read_track_events( &len ); - - /* set channel to channel of first event... */ - if ( e->size() ) - _channel = e->front().channel(); - - /* copy events into pattern */ - _rw->events = *e; - delete e; - - if ( len ) - _rw->length = len; - - unlock(); - -// print(); -} - -/** save (export) pattern to file /name/ */ -void -pattern::save ( const char *name ) const -{ - smf f; - - /* open for writing */ - f.open( name, smf::WRITE ); - - /* writing SMF 0 track */ - f.write_header( 0 ); - - f.open_track( _name, _number ); - - Grid::dump( &f, _channel ); - - f.close_track( length() ); -} - -/** dump pattern as a track in an already open MIDI file */ -void -pattern::dump ( smf *f ) const -{ - f->open_track( _name, _number ); - - f->write_pattern_info( this ); - - Grid::dump( f, _channel ); - - f->close_track( length() ); -} - - - -/*************/ -/* Recording */ -/*************/ - -void -pattern::record ( int mode ) -{ - _recording = true; - pattern::_pattern_recording = _number; -} - -void -pattern::record_stop ( void ) -{ - if ( ! _recording ) - return; - - _recording = false; - - if ( config.record_mode == NEW ) - trim(); - - pattern::_recorded_events.clear(); -} - - - -/*******************************/ -/* Pattern specific accessors. */ -/*******************************/ - - -int -pattern::port ( void ) const -{ - return _port; -} - -void -pattern::port ( int p ) -{ - _port = p; -} - -int -pattern::channel ( void ) const -{ - return _channel; -} - -void -pattern::channel ( int c ) -{ - _channel = c; -} - -int -pattern::note ( void ) const -{ - return _note; -} - -void -pattern::note ( int n ) -{ - _note = n; -} - - -int -pattern::ppqn ( void ) const -{ - return _ppqn; -} - -void -pattern::ppqn ( int n ) -{ - _ppqn = n; -} - -int -pattern::key ( void ) const -{ - return mapping.key(); -} - -void -pattern::key ( int k ) -{ - mapping.key( k ); -} diff --git a/sequencer/src/pattern.H b/sequencer/src/pattern.H deleted file mode 100644 index 3d2dab6..0000000 --- a/sequencer/src/pattern.H +++ /dev/null @@ -1,119 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007-2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "grid.H" -#include "canvas.H" -#include "mapping.H" -#include "common.h" - -#include -using std::vector; - -class pattern : public Grid -{ - static MIDI::event_list _recorded_events; - static vector _patterns; - static int _solo; - static int _pattern_recording; - - - static int solo ( void ); - - int _channel, _port; - - bool _recording; - mutable volatile bool _cleared; - - mutable volatile int _queued; - -// int _key; - - int _note; - - void _add ( void ); - - -public: - - static signal signal_create_destroy; - - Mapping mapping; - - pattern ( void ); - ~pattern ( void ); - pattern ( const pattern &rhs ); - - static int patterns ( void ); - static pattern * pattern_by_number ( int n ); - static void reset ( void ); - static pattern * import ( smf *f, int track ); - - static pattern * recording ( void ); - static void record_event ( const MIDI::midievent *e ); - - pattern * create ( void ); - pattern * by_number ( int n ) const; - - pattern * clone ( void ); - void put ( int x, int y, tick_t l ); - const char * row_name ( int r ) const; - void draw_row_names ( Canvas *c ) const; - void trigger ( tick_t start, tick_t end ); - void trigger ( void ); - void stop ( void ) const; - void play ( tick_t start, tick_t end ) const; - - void load ( smf *f ); - - void record( int mode ); - void record_stop ( void ); - - void queue ( int mode ); - int queue ( void ) const; - - void row_name_press ( int y ); - - int port ( void ) const; - void port ( int p ); - int channel ( void ) const; - void channel ( int c ); - int note ( void ) const; - void note ( int n ); - - void mode ( int n ); - int mode ( void ) const; - - int key ( void ) const; - void key ( int k ); - - int load ( const char *name ); - void save ( const char *name ) const; - void dump ( smf *f ) const; - - int ppqn ( void ) const; - void ppqn ( int n ); - - virtual tick_t default_length ( void ) const - { - return PPQN * 4 / _note; - } - -}; diff --git a/sequencer/src/phrase.C b/sequencer/src/phrase.C deleted file mode 100644 index 2d5ba68..0000000 --- a/sequencer/src/phrase.C +++ /dev/null @@ -1,274 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "phrase.H" -#include "pattern.H" -#include "smf.H" -#include "common.h" -#include - -using namespace MIDI; - -vector phrase::_phrases; -signal phrase::signal_create_destroy; - -phrase::phrase ( void ) -{ - viewport.h = 32; - viewport.w = 32; - - _add(); - - char *s; - asprintf( &s, "Phrase %d", number() ); - - name( s ); - -} - - -phrase::~phrase ( void ) -{ - DMESSAGE( "deleting phrase %d", number() ); - signal_create_destroy(); -} - -void -phrase::_add ( void ) -{ - // keep track of all the phrases - phrase::_phrases.push_back( this ); - _number = phrases(); - - signal_create_destroy(); -} - -/* copy constructor */ -phrase::phrase ( const phrase &rhs ) : Grid( rhs ) -{ - _add(); -} - -phrase * -phrase::clone ( void ) -{ - return new phrase( *this ); -} - -/******************/ -/* Static methods */ -/******************/ - -int -phrase::phrases ( void ) -{ - return phrase::_phrases.size(); -} - -phrase * -phrase::phrase_by_number ( int n ) -{ - if ( n <= phrases() && n > 0 ) - { - return phrase::_phrases[ n - 1 ]; - } - return NULL; -} - -void -phrase::reset ( void ) -{ - for ( int n = phrase::phrases(); n-- ; ) - { - delete phrase::_phrases.back(); - phrase::_phrases.pop_back(); - } -} - - - - -/*******************/ -/* Virtual Methods */ -/*******************/ - -phrase * -phrase::create ( void ) -{ - if ( phrase::phrases() < 128 ) - { - return new phrase; - } - else - return NULL; -} - -phrase * -phrase::by_number ( int n ) const -{ - return phrase::phrase_by_number( n ); -} - -void -phrase::put ( int x, int y, tick_t l, int velocity ) -{ - // FIXME: use translation here. - pattern *p = pattern::pattern_by_number( y + 1 ); - - if ( ! p ) - return; - - l = p->length(); - - Grid::put( x, y, l ); -} - -const char * -phrase::row_name ( int r ) const -{ - pattern *p = pattern::pattern_by_number( r + 1 ); - - return p ? p->name() : NULL; -} - -void -phrase::draw_row_names ( Canvas *c ) const -{ - for ( int y = viewport.h; y--; ) - { - pattern *p = pattern::pattern_by_number( y + 1 ); - - if ( p && p->name() ) - c->draw_row_name( y, p->name(), 0 ); - } -} - - -void -phrase::trigger ( tick_t start, tick_t end ) -{ - _start = start; - _end = end; -} - -// FIXME: so much of this is copied from pattern.C, there has -// to be a way to share more of this code. -void -phrase::play ( tick_t start, tick_t end ) -{ - /* get our own copy of this pointer so UI thread can change it. */ - const data *d = const_cast< const data * >(_rd); - - if ( start > _end ) - { - _playing = false; - return; - } - - if ( start < _start ) - start = _start; - - if ( end > _end ) - end = _end; - - _playing = true; - - // where we are in the absolute time - tick_t tick = start - _start; - int num_played = tick / d->length; - tick_t offset = _start + (d->length * num_played); - - _index = fmod( tick, d->length ); - - if ( _index < end - start ) - DMESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset ); - -try_again: - - // pattern is empty - if ( d->events.empty() ) - goto done; - - for ( const event *e = d->events.first(); e; e = e->next() ) - { - // MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print(); - - const tick_t ts = e->timestamp() + offset; - - if ( ts >= end ) - goto done; - - if ( e->is_note_on() ) - { - const tick_t tse = offset + e->link()->timestamp(); - - if ( tse > start ) - { - pattern *p = pattern::pattern_by_number( 1 + note_to_y( e->note() ) ); - - p->trigger( ts, tse ); - - p->play( start, end ); - } - } - } - - // ran out of events, but there's still some loop left to play. - offset += d->length; - goto try_again; - - MESSAGE( "out of events, resetting to satisfy loop" ); - -done: ; -} - - -void -phrase::load ( smf *f ) -{ - lock(); - - f->read_phrase_info( this ); - - tick_t len; - - list *me = f->read_track_events( &len ); - - _rw->events = *me; - delete me; - - if ( len ) - _rw->length = len; - - unlock(); -} - -void -phrase::dump ( smf *f ) -{ - f->open_track( _name, -1 ); - - f->write_phrase_info( this ); - - f->cue( true ); - - Grid::dump( f, 0 ); - - f->close_track( length() ); -} diff --git a/sequencer/src/phrase.H b/sequencer/src/phrase.H deleted file mode 100644 index 24cdd03..0000000 --- a/sequencer/src/phrase.H +++ /dev/null @@ -1,63 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2007,2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "grid.H" -#include "canvas.H" - -class pattern; - -#include -using std::vector; - -class phrase : public Grid -{ - - static vector _phrases; - - void _add ( void ); - -public: - - static signal signal_create_destroy; - - phrase ( void ); - ~phrase ( void ); - phrase ( const phrase &rhs ); - - static int phrases ( void ); - static phrase * phrase_by_number ( int n ); - static void reset ( void ); - - virtual bool velocity_sensitive ( void ) const { return false; } - - phrase *create ( void ); - phrase * by_number ( int n ) const; - - virtual void put ( int x, int y, tick_t l, int velocity = 64 ); - phrase * clone ( void ); - const char * row_name ( int r ) const; - void draw_row_names ( Canvas *c ) const; - void play ( tick_t start, tick_t end ); - void trigger ( tick_t start, tick_t end ); - - void load ( smf *f ); - void dump ( smf *f ); -}; diff --git a/sequencer/src/scale.C b/sequencer/src/scale.C deleted file mode 100644 index a14323b..0000000 --- a/sequencer/src/scale.C +++ /dev/null @@ -1,217 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "scale.H" -#include "common.h" - -#include "stdlib.h" -#include - -using namespace MIDI; - -/* Define some scales. These don't really need to be stored on - disk. Scales don't change that often. */ - -const char *Scale::chromatic_names[] = -/* { "A", */ -/* "A#/Bb", */ -/* "B", */ -/* "C", */ -/* "C#/Db", */ -/* "D", */ -/* "D#/Eb", */ -/* "E", */ -/* "F", */ -/* "F#/Gb", */ -/* "G", */ -/* "G#/Ab" }; */ - -/* { "C", */ -/* "C#/Db", */ -/* "D", */ -/* "D#/Eb", */ -/* "E", */ -/* "F", */ -/* "F#/Gb", */ -/* "G", */ -/* "G#/Ab", */ -/* "A", */ -/* "A#/Bb", */ -/* "B" }; */ - - -{ "C", - "C#", - "D", - "D#", - "E", - "F", - "F#", - "G", - "G#", - "A", - "A#", - "B" }; - - -Scale Scale::builtin_scales[] = { - { "Major", - 7, - { 0, 2, 4, 5, 7, 9, 11 } }, - { "Natural Minor", - 7, - { 0, 2, 3, 5, 7, 8, 10 } }, - { "Harmonic Minor", - 7, - { 0, 2, 3, 5, 7, 8, 11 } }, - { "Melodic Minor", - 7, - { 0, 2, 3, 5, 7, 9, 11 } }, - { "Major Pentatonic", - 5, - { 0, 2, 4, 7, 9 } }, - { "Minor Pentatonic", - 5, - { 0, 3, 5, 7, 10 } }, - { "Chromatic", - 12, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } } -}; - -/* const Scale builtin_chords[] = { */ -/* { "Major Triad", */ -/* { 0, 4, 7, -1 } }, */ -/* { "Major Sixth", */ -/* { 0, 4, 7, 9, -1 } }, */ -/* { "Major Seventh", */ -/* { 0, 4, 7, 11, -1 } }, */ -/* { "Major Ninth", */ -/* { 0, 4, 7, 11, 14, -1 } }, */ -/* { "Major 6/9", */ -/* { 0, 4, 7, 9, 14, -1 } }, */ -/* { "Major Eleventh", */ -/* { 0, 4, 7, 11, 14, 17, -1 } }, */ -/* { "Major Thirteenth", */ -/* { 0, 4, 7, 11, 14, 17, 21, -1 } }, */ - -/* { "Minor Triad", */ -/* { 0, 3, 7, -1 } }, */ -/* { "Minor Sixth", */ -/* { 0, 3, 7, 9, -1 } }, */ -/* { "Minor Seventh", */ -/* { 0, 3, 7, 10, -1 } }, */ -/* { "Minor Ninth", */ -/* { 0, 3, 7, 10, 14, -1 } }, */ -/* { "Minor 6/9", */ -/* { 0, 3, 7, 9, 14, -1 } }, */ -/* { "Minor Eleventh", */ -/* { 0, 3, 7, 10, 14, 17, -1 } }, */ -/* { "Minor Thirteenth", */ -/* { 0, 3, 7, 10, 14, 17, 21, -1 } }, */ - -/* { "Augmented Triad", */ -/* { 0, 4, 8, -1 } }, */ -/* { "Diminished Triad", */ -/* { 0, 3, 6, -1 } } */ -/* }; */ - - -/* "Opens" a scale for compatibility with Instrument class */ -Scale * -Scale::open ( const char *name ) -{ - for ( int i = elementsof( builtin_scales ) - 1; i >= 0; --i ) - if ( 0 == strcmp( name, builtin_scales[i]._name ) ) - return &builtin_scales[i]; - - return NULL; -} - -/* Returns a list of available scales */ -char ** -Scale::listing ( void ) -{ - char **sa; - - int n = elementsof( builtin_scales ); - - sa = (char **)malloc( sizeof ( char * ) * ( n + 1 ) ); - sa[n] = NULL; - - while ( n-- ) - sa[n] = strdup( builtin_scales[n]._name ); - - return sa; -} - -const char * -Scale::chromatic_name ( int n ) -{ - return chromatic_names[ n % 12 ]; -} - -int -Scale::octave ( int n ) -{ - return n / 12; -} - -int -Scale::_degree ( int k, int n ) const -{ - return k + _degrees[ n % _notes ]; -} - -/* translate NOTE event. Behavior is undefined for other event types */ -bool -Scale::translate ( int k, midievent *e ) const -{ - if ( ! note_name( k, e->note() ) ) - return false; - else - return true; -} - -const char * -Scale::note_name ( int k, int n ) const -{ - /* all the magic is here */ - static char s[5]; - - const int mod_n = n % 12; - - // FIXME: searching is not efficient! - for ( int i = _notes; i-- ; ) - if ( mod_n == (_degrees[ i ] + k) % 12 ) - { - snprintf( s, sizeof(s), "%s%i", - chromatic_names[ mod_n ], - n / 12 ); - - return s; - } - - return NULL; -} - -const char * -Scale::name ( void ) const -{ - return _name; -} diff --git a/sequencer/src/scale.H b/sequencer/src/scale.H deleted file mode 100644 index 61f0ffb..0000000 --- a/sequencer/src/scale.H +++ /dev/null @@ -1,47 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once -#include - -class Scale -{ - - static const char *chromatic_names[]; - static Scale builtin_scales[]; - - int _degree ( int k, int n ) const; - -public: - const char *_name; - int _notes; - int _degrees[13]; - -public: - - static Scale * open ( const char *name ); - static char ** listing ( void ); - static const char * chromatic_name ( int n ); - static int octave ( int n ); - - bool translate ( int k, MIDI::midievent *e ) const; - int note ( int k, int n ) const; - const char * note_name ( int k, int n ) const; - const char * name ( void ) const; -}; diff --git a/sequencer/src/sequence.C b/sequencer/src/sequence.C deleted file mode 100644 index c6a0c38..0000000 --- a/sequencer/src/sequence.C +++ /dev/null @@ -1,456 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "sequence.H" -#include "phrase.H" -#include "pattern.H" -#include "smf.H" - -#include "non.H" - -#include - -/* #include */ - -/* using std::string; */ - -sequence::sequence ( void ) -{ - _rd = new data; - _name = _notes = NULL; - - _index = 0; - _playing = 0; -} - - -void -sequence::lock ( void ) -{ - // create a copy of the lock-free data. - _rw = new data; - - data *d = const_cast< data *> (_rd); - - _rw->phrases = d->phrases; - _rw->num = d->num; -} - -void -sequence::unlock ( void ) -{ - _history.push_back( const_cast( _rd ) ); - - if ( _history.size() > MAX_UNDO + 1 ) - { - data *d = _history.front(); - - if ( d == _rw || d == _rd ) - ASSERTION( "something bad has happend." ); - - delete d; - - _history.pop_front(); - } - - // swap the copy back in (atomically). - _rd = _rw; - - _rw = NULL; - - song.set_dirty(); -} - -void -sequence::insert ( unsigned int n, int pn ) -{ - lock(); - -/* if ( n > _rw->phrases.size() ) */ -/* _rw->phrases.resize( n + 10 ); */ - -// MESSAGE( "inserting %d at %d", pn, n ); - - _rw->phrases.insert( _find( n ), pn ); - _rw->num++; - - unlock(); -} - -vector ::iterator -sequence::_find ( int n ) -{ - // boy I hate C++/STL.. So lame. - int i = 0; - for ( vector ::iterator e = _rw->phrases.begin(); e != _rw->phrases.end(); e++ ) - { - if ( i == n ) - return e; - i++; - } - - return _rw->phrases.end(); -} - -void -sequence::remove ( int n ) -{ - lock(); - - _rw->phrases.erase( _find( n ) ); - _rw->num--; - - unlock(); -} - -/** return the number of phrases in this sequence */ -int -sequence::phrases ( void ) const -{ - return _rd->num; -} - -void -sequence::_swap ( int n1, int n2 ) -{ - int x = _rw->phrases[ n1 ]; - _rw->phrases[ n1 ] = _rw->phrases[ n2 ]; - _rw->phrases[ n2 ] = x; -} - -void -sequence::move ( int n, int dir ) -{ - lock(); - - switch ( dir ) - { - case UP: - { - if ( n - 1 >= 0 ) - _swap( n - 1, n ); - break; - } - case DOWN: - { - if ( n + 1 < _rw->num ) - _swap( n + 1, n ); - break; - } - - } - - unlock(); -} - -/* Render sequence to a string.. suitable for display in the UI */ -char * -sequence::dump ( void ) -{ - char *s = (char *)malloc( 256 ); - s[0] = '\0'; - size_t siz = 256; - - int start = 1; - for ( int i = 0; i < _rd->num; i++ ) - { - const int len = 256; - - char line[len]; - - int x = _rd->phrases[ i ]; - - phrase *p = phrase::phrase_by_number( x ); - - if ( ! p ) - return NULL; - - snprintf( line, len, "%d\t%d\t%s\n", start, p->number(), p->name() ); - - start += p->bars(); - - s = (char *)realloc( s, siz += strlen( line ) + 1 ); - - strcat( s, line ); - } - return s; -} - - -void -sequence::play ( tick_t start, tick_t end ) const -{ - // keep our own copy. - data *d = _rd; - - tick_t offset = 0; - for ( int i = 0; i < d->num; i++ ) - { - phrase *p = phrase::phrase_by_number( d->phrases[ i ] ); - if ( p ) - { - tick_t pstart = offset; - tick_t pend = offset + p->length(); - - // this phrase seems to be current. - if ( pend > start && pstart <= end ) - { - p->trigger( pstart, pend ); - - _playing = p->number(); - - _index = start; - - p->play( start, end ); - } - - offset = pend; - } - else - WARNING( "programming error: no such phrase." ); - } -} - -/** return the number of the currently playing phrase, or 0 if none. */ -int -sequence::playing ( void ) const -{ - return _playing; -} - -/** return the location of the playhead for this sequence */ -tick_t -sequence::index ( void ) const -{ - return _index; -} - -/** return the total length of the sequence in ticks */ -tick_t -sequence::length ( void ) const -{ - tick_t l = 0; - - for ( int i = 0; i < _rd->num; i++ ) - { - phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] ); - - if ( ! p ) - break; - - l += p->length(); - } - - return l; -} - -/** return to a blank slate */ -void -sequence::reset ( void ) -{ -// MESSAGE( "reseting" ); - - lock(); - - _rw->num = 0; - - phrase::reset(); - pattern::reset(); - - unlock(); -} - -/** load entire sequence from file, replacing everything */ -bool -sequence::load ( const char *name ) -{ - smf f; - - if ( ! f.open( name, smf::READ ) ) - { - WARNING( "error opening file: %s", strerror( errno ) ); - return false; - } - - f.read_header(); - - if ( f.format() != 2 ) - { - WARNING( "not a Non song file" ); - return false; - } - - f.next_track(); - - DMESSAGE( "reading song info" ); - - /* read song info */ - int mode = PATTERN; - int phrases = 0; - int patterns = 0; - char *sname = NULL; - char *notes = NULL; - - if ( ! f.read_song_info( &mode, &phrases, &patterns, &sname, ¬es ) ) - { - WARNING( "not a Non song file" ); - return false; - } - - song.play_mode = (play_mode_e)mode; - - if ( sname ) - this->name( sname ); - - if ( notes ) - this->notes( notes ); - - /* tear it down */ - reset(); - - DMESSAGE( "reading playlist" ); - -// f.read_playlist( this ); - - lock(); - - char *s; - while ( (s = f.read_cue_point() ) ) - { - int n; - - sscanf( s, "%d:", &n ); - - _rw->phrases.insert( _find( _rw->num++ ), n ); - } - - /* read playlist */ - - DMESSAGE( "reading phrases" ); - - while ( phrases-- && f.next_track() ) - { - phrase *p = new phrase; - - p->load( &f ); - } - - DMESSAGE( "reading patterns" ); - - while ( patterns-- && f.next_track() ) - { - pattern *p = new pattern; - - p->load( &f ); - } - - unlock(); - - signal_new_song(); - - return true; -} - -/** save entire sequence to file */ -void -sequence::save ( const char *name ) const -{ - smf f; - - /* open for writing */ - f.open( name, smf::WRITE ); - - f.write_header( 2 ); - - DMESSAGE( "saving playlist" ); - - f.open_track( NULL, -1 ); - - DMESSAGE( "saving song info" ); - - f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() ); - - for ( int i = 0; i < _rd->num; ++i ) - { - char pat[256]; - - phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] ); - - snprintf( pat, 256, "%d: %s", p->number(), p->name() ); - - f.write_meta_event( smf::CUEPOINT, pat ); - } - - f.close_track( 0 ); - - DMESSAGE( "saving phrases" ); - - for ( int i = 0; i < phrase::phrases(); i++ ) - { - phrase *p = phrase::phrase_by_number( i + 1 ); - - p->dump( &f ); - } - - DMESSAGE( "saving patterns" ); - - for ( int i = 0; i < pattern::patterns(); i++ ) - { - pattern *p = pattern::pattern_by_number( i + 1 ); - - p->dump( &f ); - } -} - - -/*************/ -/* Accessors */ -/*************/ - -char * -sequence::name ( void ) const -{ - return _name; -} - -void -sequence::name ( const char *s ) -{ - if ( _name ) free( _name ); - - _name = strdup( s ); - - song.set_dirty(); -} - -char * -sequence::notes ( void ) const -{ - return _notes; -} - -void -sequence::notes ( const char *s ) -{ - if ( _notes ) free( _notes ); - - _notes = strdup( s ); - - song.set_dirty(); -} diff --git a/sequencer/src/sequence.H b/sequencer/src/sequence.H deleted file mode 100644 index 321abd4..0000000 --- a/sequencer/src/sequence.H +++ /dev/null @@ -1,85 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include - -#include - -#include "common.h" - -using std::vector; -using std::list; -using namespace sigc; - -class sequence : public trackable { - - struct data { - vector phrases; - int num; - - data() { num = 0; } - }; - - list _history; - - data *_rd; - data *_rw; - - char * _name; - char * _notes; - - mutable volatile int _playing; - mutable volatile tick_t _index; - - void lock ( void ); - void unlock ( void ); - - vector ::iterator _find ( int n ); - - void _swap ( int n1, int n2 ); - -public: - - signal signal_new_song; - - sequence( void ); - - void reset ( void ); - - void insert ( unsigned int n, int pn ); - void remove ( int n ); - void move ( int n, int dir ); - int phrases ( void ) const; - char * dump ( void ); - bool load ( const char *name ); - void save ( const char *name ) const; - void play ( tick_t start, tick_t end ) const; - int playing ( void ) const; - tick_t index ( void ) const; - tick_t length ( void ) const; - - char * name ( void ) const; - void name ( const char *s ); - char * notes ( void ) const; - void notes ( const char *s ); - -}; diff --git a/sequencer/src/smf.C b/sequencer/src/smf.C deleted file mode 100644 index 4ae2fb3..0000000 --- a/sequencer/src/smf.C +++ /dev/null @@ -1,1162 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "smf.H" -#include "phrase.H" -#include "pattern.H" - -using namespace MIDI; - -smf::smf ( void ) -{ - _name = NULL; - _pos = 0; - - _fp = NULL; - - _length = 0; - _length_pos = 0; - _num_tracks_pos = 0; - _tracks = 0; - _time = 0; - _tally = 0; - _cue = 0; - _track = 0; -} - -smf::~smf ( void ) -{ - /* fill in the number of tracks */ - if ( _num_tracks_pos ) - { - fseek( _fp, _num_tracks_pos, SEEK_SET ); - write_short( _tracks ); - } - - if ( _fp ) - fclose( _fp ); - - if ( _name ) - free( _name ); -} - -int -smf::open ( const char *name, int mode ) -{ - _name = strdup( name ); - - _mode = mode; - - _fp = fopen( _name, mode == smf::WRITE ? "w" : "r" ); - - return _fp != NULL; -} - -/*************************/ -/* Private bit twiddlers */ -/*************************/ - -unsigned long -smf::read_long ( void ) -{ - byte_t buf[4]; - unsigned long ret = 0; - - read_bytes( buf, 4 ); - - ret += *(buf + 0) << 24; - ret += *(buf + 1) << 16; - ret += *(buf + 2) << 8; - ret += *(buf + 3); - - return ret; -} - -unsigned short -smf::read_short ( void ) -{ - byte_t buf[2]; - unsigned short ret = 0; - - read_bytes( buf, 2 ); - - ret += *(buf + 0) << 8; - ret += *(buf + 1); - - return ret; -} - -unsigned long -smf::read_var ( void ) -{ - unsigned long ret = 0; - unsigned char c; - - /* while bit #7 is set */ - while ( ( ( c = read_byte() ) & 0x80 ) != 0x00 ) - { - - /* shift ret 7 bits */ - ret <<= 7; - /* add bits 0-6 */ - ret += c & 0x7F; - } - - /* bit was clear */ - ret <<= 7; - ret += c & 0x7F; - - return ret; -} - -void -smf::read_bytes ( void *p, int l ) -{ - fread( p, l, 1, _fp ); - - _pos += l; -} - -byte_t -smf::read_byte ( void ) -{ - byte_t b; - read_bytes( &b, 1 ); - - return b; -} - -void -smf::write_var ( long var ) -{ - long buffer; - buffer = var & 0x7F; - - /* we shift it right 7, if there is - still set bits, encode into buffer - in reverse order */ - while ( ( var >>= 7) ) - { - buffer <<= 8; - buffer |= ( var & 0x7F ) | 0x80; - } - - for ( ;; ) - { - write_byte( buffer ); - - if ( buffer & 0x80 ) - buffer >>= 8; - else - break; - } -} - - -void -smf::write_long ( unsigned long x ) -{ - byte_t buf[4]; - - buf[0] = ( x & 0xFF000000 ) >> 24; - buf[1] = ( x & 0x00FF0000 ) >> 16; - buf[2] = ( x & 0x0000FF00 ) >> 8; - buf[3] = x & 0x000000FF; - - write_bytes( buf, 4 ); -} - -void -smf::write_ascii ( const char *buf ) -{ - if ( strlen( buf ) != 4 ) - ASSERTION( "invalid MIDI value" ); - - write_bytes( (void *)buf, 4 ); -} - -void -smf::write_short ( unsigned short x ) -{ - byte_t buf[2]; - - buf[0] = (x & 0xFF00 ) >> 8; - buf[1] = x & 0x00FF; - - write_bytes( buf, 2 ); -} - -void -smf::write_byte ( byte_t b ) -{ - write_bytes( &b, 1 ); -} - - -void -smf::write_bytes ( const void *p, size_t l ) -{ - fwrite( p, l, 1, _fp ); - _tally += l; -} - - - -/*************************/ -/* Read and write tracks */ -/*************************/ - -/* write event /e/ to the currently open file (should only be used in a track) - if /cue/ is true, transform a notes-on/off into cue messages */ -void -smf::write_event ( const midievent *e ) -{ - tick_t ts = e->timestamp(); - tick_t delta = ts - _time; - _time = ts; - - write_var( delta ); - - if ( _cue && (e->is_note_off() || e->is_note_on() ) ) - { - /* begin cue message */ - write_byte( 0xF0 ); /* sysex */ - - write_var( 7 ); /* length of this message */ - - static byte_t data[] = { 0x7F, /* MTC */ - 0, /* id */ - 0x05 }; /* cue message */ - - write_bytes( data, sizeof( data ) ); - - write_byte( e->opcode() == event::NOTE_ON ? 0x05 : 0x06 ); - write_short( e->note() ); - - /* terminate */ - write_byte( 0xF7 ); - - _status = 0; - } - else - { - byte_t buf[4]; - - int l = e->size(); - - midievent me = *e; - - if ( me.opcode() == event::NOTE_OFF ) - { - me.opcode( event::NOTE_ON ); - me.note_velocity( 0 ); - } - - me.raw( buf, l ); - - /* write with running status */ - if ( buf[0] != _status ) - { - write_bytes( buf, l ); - _status = buf[0]; - } - else - write_bytes( buf + 1, l - 1 ); - - } -} - -void -smf::write_header ( int fmt ) -{ - write_ascii( "MThd" ); - write_long( 6 ); /* Always 6 bytes of header */ - - _format = fmt; - - write_short( fmt ); /* format, SMF-0 for 1 track SMF-2 for more */ - - _num_tracks_pos = ftell( _fp ); - _tracks = 0; - - write_short( 0xDEAF ); - - write_short( PPQN ); -} - -/* start a new MIDI 'chunk', /id/ is 4 letters of ASCII */ -void -smf::open_chunk ( const char *id ) -{ - if ( _length_pos ) - ASSERTION( "chunks cannot be nested!" ); - - write_ascii( id ); - - /* reset track length counter */ - _length_pos = ftell( _fp ); - - write_long( 0xBEEFCAFE ); /* length, this has to be filled in at track end! */ - - _tally = 0; - _time = 0; -} - -void -smf::close_chunk ( void ) -{ - /* fill in track length */ - long here = ftell( _fp ); - - fseek( _fp, _length_pos, SEEK_SET ); - - write_long( _tally ); - - fseek( _fp, here, SEEK_SET ); - - /* cleanup */ - _length_pos = 0; - _tally = 0; -} - -void -smf::open_track ( const char *name, int num ) -{ - open_chunk( "MTrk" ); - - if ( _format == 2 && num >= 0 ) - write_meta_event ( smf::SEQUENCE, num ); - - if ( name ) - write_meta_event ( smf::NAME, name ); - - ++_tracks; - - _status = 0; - - // FIXME: write time signature here -} - -void -smf::close_track ( tick_t length ) -{ - /* end */ - write_meta_event( smf::END, length ? length - _time : 0 ); - - _cue = 0; - - close_chunk(); -} - -void -smf::write_meta_event ( byte_t type, int n ) -{ - write_var( type == smf::END ? n : 0 ); /* delta time */ - write_short( 0xFF00 + type ); - - /* write length bytes */ - switch ( type ) - { - case smf::TEMPO: - write_byte( 3 ); -// FIXME: - break; - case smf::SEQUENCE: - write_byte( 2 ); - write_short( n ); - break; - case smf::CHANNEL: - case smf::PORT: - write_byte( 1 ); - write_byte( n ); - break; - case smf::END: - write_byte( 0x00 ); - break; - case smf::PROPRIETARY: - // length - write_var( n ); - break; -// FIXME: handle time sig, key sig, proprietary - } - - _status = 0; -} - -void -smf::write_meta_event ( byte_t type, const char *s ) -{ - write_var( 0 ); - write_short( 0xFF00 + type ); - - switch ( type ) - { - case smf::TEXT: - case smf::NAME: - case smf::INSTRUMENT: - case smf::COPYRIGHT: - case smf::LYRIC: - case smf::MARKER: - case smf::CUEPOINT: - { - int l = strlen( s ); - - write_var( l ); - - write_bytes( s, l ); - - break; - } - default: - ASSERTION( "event type does not take text!" ); - break; - } -} - -/** write song gloabl info (only used on playlist track) */ -void -smf::write_song_info ( int mode, int phrases, int patterns, const char *name, const char *notes ) -{ - write_meta_event( smf::PROPRIETARY, 5 + (4 * 2) /* length */ ); - - write_ascii( "Non!" ); - - write_byte( mode ); - write_long( phrases ); - write_long( patterns ); - - if ( name ) - write_meta_event( smf::NAME, name ); - - write_meta_event( smf::TEXT, ":: Created by the Non-Seqeuncer" ); - - if ( notes ) - write_meta_event( smf::TEXT, notes ); -} - -void -smf::write_phrase_info ( const phrase *p ) -{ - if ( p->notes() ) - write_meta_event( smf::TEXT, p->notes() ); - - char *s = p->viewport.dump(); - - char pat[156]; - snprintf( pat, sizeof( pat ), "Non: xywh=%s", - s ); - - free( s ); - - write_meta_event( smf::PROPRIETARY, strlen( pat ) ); - write_bytes( pat, strlen( pat ) ); -} - -/** write proprietary pattern info meta event */ -void -smf::write_pattern_info ( const pattern *p ) -{ - write_meta_event( smf::PORT, p->port() ); - - char pat[256]; - - snprintf( pat, sizeof( pat ), "%s: %s", p->mapping.type(), p->mapping.name() ); - - write_meta_event( smf::INSTRUMENT, pat ); - - if ( p->notes() ) - write_meta_event( smf::TEXT, p->notes() ); - - char *s = p->viewport.dump(); - - snprintf( pat, sizeof( pat ), "Non: xywh=%s, ppqn=%d, key=%d, note=%d, mode=%d", - s, p->ppqn(), p->mapping.key(), p->note(), p->mode() ); - - free( s ); - - write_meta_event( smf::PROPRIETARY, strlen( pat ) ); - write_bytes( pat, strlen( pat ) ); -} - -/* turn on note->cue translation for this track */ -void -smf::cue ( bool b ) -{ - _cue = b; -} - - -/**********/ -/* Reader */ -/**********/ - -char * -smf::read_text ( void ) -{ - int l = read_var(); - - char *s = (char*) malloc( l + 1 ); - - read_bytes( s, l ); - - s[l] = '\0'; - - return s; -} - - -int -smf::read_header ( void ) -{ - char id[4]; - read_bytes( id, 4 ); - - if ( strncmp( id, "MThd", 4 ) ) - return 0; - - if ( read_long() != 6 ) - return 0; - - _format = read_short(); - _tracks = read_short(); - _ppqn = read_short(); - - _pos = 0; - - return 1; -} - -void -smf::home ( void ) -{ - fseek( _fp, 14, SEEK_SET ); - - _track = 0; - _pos = 0; - _length = 0; -} - -void -smf::skip ( size_t l ) -{ - fseek( _fp, l, SEEK_CUR ); - _pos += l; -} - -void -smf::backup ( size_t l ) -{ - skip( 0 - l ); -} - -char * -smf::read_track_name ( void ) -{ - int status; - long where = 0; - int num = 0; - - for ( num = 0; ; ++num ) - { - where = _pos; - - read_var(); /* delta */ - status = read_byte(); - - /* stop at first non meta-event */ - if ( status != midievent::META ) - break; - - int opcode = read_byte(); - - switch ( opcode ) - { - case smf::NAME: - return read_text(); - case smf::TEXT: - return read_text(); - default: - skip( read_var() ); - } - } - - backup( _pos - where ); - - return NULL; -} - -/** read next Cue Point event on track */ -char * -smf::read_cue_point ( void ) -{ - read_var(); /* delta */ - - int status = read_byte(); - - if ( status != midievent::META ) - return NULL; - - int opcode = read_byte(); - - if ( opcode != smf::CUEPOINT ) - return NULL; - - return read_text(); -} - -bool -smf::read_song_info ( int * mode, int * phrases, int *patterns, char **name, char **notes ) -{ - int status; - long where = 0; - int num = 0; - bool r = false; - *notes = NULL; - - for ( num = 0; ; ++num ) - { - where = _pos; - - read_var(); /* delta */ - status = read_byte(); - - /* stop at first non meta-event */ - if ( status != midievent::META ) - break; - - int opcode = read_byte(); - - switch ( opcode ) - { - case smf::PROPRIETARY: - { - int len = read_var(); - - if ( len < 5 + (2 * 4) ) - return false; - - char id[4]; - read_bytes( id, 4 ); - - if ( strncmp( id, "Non!", 4 ) ) - return false; - - *mode = read_byte(); - *phrases = read_long(); - *patterns = read_long(); - - r = true; - - break; - } - case smf::TEXT: - { - char *text = read_text(); - - if ( ! strncmp( text, "::", 2 ) ) - free( text ); - else - *notes = text; - - break; - } - case smf::NAME: - *name = read_text(); - break; - case smf::END: - goto done; - default: - goto semidone; - } - } - -semidone: - - backup( _pos - where ); - -done: - - return r; -} - -bool -smf::read_phrase_info ( phrase *p ) -{ - int status; - long where = 0; - int num = 0; - - for ( num = 0; ; ++num ) - { - where = _pos; - - read_var(); /* delta */ - status = read_byte(); - - /* stop at first non meta-event */ - if ( status != midievent::META ) - break; - - int opcode = read_byte(); - - switch ( opcode ) - { - case smf::SEQUENCE: - /* currently, this is ignored */ - read_var(); - read_short(); - break; - case smf::NAME: - p->name( read_text() ); - DMESSAGE( "Track name: %s", p->name() ); - break; - case smf::INSTRUMENT: - skip( read_var() ); - break; - case smf::TEXT: - p->notes( read_text() ); - break; - case smf::PROPRIETARY: - { - int l = read_var(); - - char *data = (char *) alloca( l ) + 1; - - read_bytes( data, l ); - - data[l] = '\0'; - - char *s; - - if ( 1 != sscanf( data, "Non: xywh=%m[0-9:]", - &s ) ) - WARNING( "Invalid phrase info event" ); - else - { - p->viewport.read( s ); - free( s ); - } - break; - } - case smf::END: - /* Track ends before any non meta-events... */ - read_byte(); - goto done; - default: - int l = read_var(); - skip( l ); - WARNING( "skipping unrecognized meta event %02X", opcode ); - break; - } - } - - backup( _pos - where ); - -done: - - return num ? p : NULL; -} - -/** inform pattern /p/ from meta-events at the beginning of the - current track */ -bool -smf::read_pattern_info ( pattern *p ) -{ - int status; - long where = 0; - int num = 0; - - bool name_set = false; - - for ( num = 0; ; ++num ) - { - where = _pos; - - read_var(); /* delta */ - status = read_byte(); - - /* stop at first non meta-event */ - if ( status != midievent::META ) - break; - - int opcode = read_byte(); - - switch ( opcode ) - { - case smf::SEQUENCE: - /* currently, this is ignored */ - read_var(); - read_short(); - break; - case smf::NAME: - p->name( read_text() ); - DMESSAGE( "Track name: %s", p->name() ); - name_set = true; - break; - case smf::INSTRUMENT: - { - char *s = read_text(); - - char pat[256]; - - if ( 1 == sscanf( s, "Instrument: %[^\n]", pat ) ) - { - if ( ! p->mapping.open( Mapping::INSTRUMENT, pat ) ) - { - p->mapping.open( Mapping::SCALE, "Chromatic" ); - WARNING( "could not find instrument \"%s\"", pat ); - } - } - else - if ( 1 == sscanf( s, "Scale: %[^\n]", pat ) ) - { - if ( ! p->mapping.open( Mapping::SCALE, pat ) ) - { - p->mapping.open( Mapping::SCALE, "Chromatic" ); - WARNING( "could not find scale \"%s\"", pat ); - } - } - break; - } - case smf::PORT: - read_byte(); - p->port( read_byte() ); - break; - case smf::TEXT: - if ( ! name_set ) - { - /* also accept TEXT event as name if no name was - provided--this is found in a number of older MIDI - files. */ - p->name( read_text() ); - name_set = true; - } - else - p->notes( read_text() ); - break; - case smf::PROPRIETARY: - { - int l = read_var(); - - char *data = (char *) alloca( l ) + 1; - - read_bytes( data, l ); - - data[l] = '\0'; - - int ppqn, key, note, mode; - char *s; - - if ( 5 != sscanf( data, "Non: xywh=%m[0-9:], ppqn=%d, key=%d, note=%d, mode=%d", - &s, &ppqn, &key, ¬e, &mode ) ) - WARNING( "Invalid pattern info event" ); - else - { - p->viewport.read( s ); - free( s ); - - p->ppqn( ppqn ); - - if ( key > 0 ) - p->mapping.key( key ); - - p->note( note ); - p->mode( mode ); - } - break; - } - case smf::END: - /* Track ends before any non meta-events... */ - read_byte(); - goto done; - default: - int l = read_var(); - skip( l ); - WARNING( "skipping unrecognized meta event %02X", opcode ); - break; - } - } - - backup( _pos - where ); - -done: - - return num ? p : NULL; -} - -int -smf::next_track ( void ) -{ - /* first, skip to the end of the track we're on, if any */ - if ( _length ) - skip( _length - _pos ); - - while ( ! feof( _fp ) && _track < _tracks ) - { - char id[4]; - read_bytes( id, 4 ); - _length = read_long(); - - if ( strncmp( id, "MTrk", 4 ) ) - { - WARNING( "skipping unrecognized chunk \"%s\"", id ); - /* not a track chunk */ - skip( _length ); - continue; - } - - _pos = 0; - ++_track; - return 1; - } - - return _length = _pos = 0; -} - - -/** locate track number /n/ */ -bool -smf::seek_track ( int n ) -{ - home(); - - if ( n >= _tracks ) - return false; - - for ( int i = 0; next_track(); ++i ) - if ( i == n ) - break; - - return true; -} - -char ** -smf::track_listing ( void ) -{ - if ( _pos != 0 ) - ASSERTION( "attempt to get track listing while in the middle of reading a track." ); - - char **sa = (char**)malloc( sizeof( char* ) * (_tracks + 1) ); - int i; - - long where = ftell( _fp ); - - for ( i = 0; next_track(); ++i ) - { - sa[i] = read_track_name(); - sa[i] = sa[i] ? sa[i] : strdup( "" ); - } - - sa[i] = NULL; - - /* go back to where we started */ - fseek( _fp, where, SEEK_SET ); - _pos = 0; - - return sa; -} - -/* print track list for file /name/ */ -void -smf::print_track_listing ( const char *name ) -{ - smf f; - - f.open( name, smf::READ ); - - f.read_header(); - - char **sa = f.track_listing(); - - char *s; - for ( int i = 0; (s = sa[i]); ++i ) - printf( "Track %3d: \"%s\"\n", i, s ); -} - -/** read all remaining events in current track and return them in a list */ -list * -smf::read_track_events ( tick_t *length ) -{ - list *events = new list ; - event e; - - *length = 0; - - byte_t oldstatus = -1; - tick_t time = 0; - tick_t tick = 0; - tick_t delta; - - while ( _pos < _length ) - { - byte_t data[3]; - - delta = read_var(); - - int status = read_byte(); - - if ( ! (status & 0x80) ) - { - backup( 1 ); - status = oldstatus; - } - else - oldstatus = status; - - time += delta; - tick = (time * PPQN) / _ppqn; - - e.timestamp( tick ); - - int opcode = status & 0xF0; - -// e.status( opcode ); - e.status( status ); - - switch ( opcode ) - { - case event::NOTE_OFF: - case event::NOTE_ON: - case event::AFTERTOUCH: - case event::CONTROL_CHANGE: - case event::PITCH_WHEEL: - - read_bytes( data, 2 ); - - /* handle note off, vel 0 */ - if ( opcode == event::NOTE_ON && 0 == data[1] ) - { - e.opcode( event::NOTE_OFF ); - data[1] = 127; - } - - e.data( data[0], data[1] ); - - events->push_back( e ); - - /* TODO: set MIDI channel here */ - break; - case event::PROGRAM_CHANGE: - case event::CHANNEL_PRESSURE: - - data[0] = read_byte(); - - e.lsb( data[0] ); - - events->push_back( e ); - break; - case 0xF0: - /* TODO: hanlde proprietary events? */ - if ( midievent::META != status ) - { - if ( 0xF0 == status ) - { - /* looks like a sysex */ - int l = read_var(); - - if ( l < 4 ) - ASSERTION( "unrecognized message" ); - - byte_t *data = (byte_t *) alloca( 4 ); - - read_bytes( data, 4 ); - - l -= 4; - - if ( data[0] == 0x7F && - data[2] == 0x05 ) - { - /* looks like a cue message! */ - - switch ( data[3] ) - { - case 0x05: - /* start */ - e.status( event::NOTE_ON ); - e.note( read_short() ); - events->push_back( e ); - l -= 2; - break; - case 0x06: - /* stop */ - e.status( event::NOTE_OFF ); - e.note( read_short() ); - events->push_back( e ); - l -= 2; - break; - default: - ASSERTION( "unrecognized cue message" ); - break; - } - } - - DMESSAGE( "converting MIDI cue to note-on/off n: %d", e.note() ); - - /* just in case */ - skip( l ); - } - else - { - WARNING( "unrecognized opcode %02X", status ); - // FIXME: what now? - } - break; - } - - opcode = read_byte(); - - switch ( opcode ) - { - case smf::END: /* track end */ - /* track extends until this event */ - *length = tick; - - if ( read_byte() ) - WARNING( "corrupt MIDI file in track end" ); - goto done; - break; - default: - WARNING( "unhandled meta-event %02X", opcode ); - skip( read_var() ); - break; - } - } - } - -done: - - return events; -} - - -/**************************/ -/* accessors (for reader) */ -/**************************/ - -int -smf::format ( void ) const -{ - return _format; -} - -int -smf::tracks ( void ) const -{ - return _tracks; -} diff --git a/sequencer/src/smf.H b/sequencer/src/smf.H deleted file mode 100644 index ad96db9..0000000 --- a/sequencer/src/smf.H +++ /dev/null @@ -1,143 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "grid.H" - -class pattern; -class phrase; - -#include - -class smf -{ - - char * _name; - - int _format; /* 0, 1, 2 */ - - FILE *_fp; - - /* reader */ - long _length; /* length of the current chunk */ - long _pos; /* number of bytes read from chunk */ - int _ppqn; /* PPQN of imported files */ - - /* writer */ - unsigned int _tally; /* number of bytes written thus far */ - long _num_tracks_pos; /* where to write the number of tracks when known */ - long _length_pos; /* where to write the chunk length when known */ - int _cue; /* transform note ons to cue events for this track */ - - int _tracks; /* number of tracks */ - int _track; /* current track */ - tick_t _time; /* current timestamp in writer */ - - int _mode; - - byte_t _status; - -public: - - enum { WRITE, READ }; - - unsigned long read_long ( void ); - unsigned short read_short ( void ); - unsigned long read_var ( void ); - void read_bytes ( void *p, int l ); - byte_t read_byte ( void ); - - void write_var ( long var ); - void write_long ( unsigned long x ); - void write_ascii ( const char *buf ); - void write_short ( unsigned short x ); - void write_byte ( byte_t b ); - void write_bytes ( const void *p, size_t l ); - -/* Meta Event codes */ - enum { - SEQUENCE = 0x00, - TEXT = 0x01, - COPYRIGHT = 0x02, - NAME = 0x03, - INSTRUMENT = 0x04, - LYRIC = 0x05, - MARKER = 0x06, - CUEPOINT = 0x07, - PROGRAM = 0x08, - DEVICE = 0x09, - CHANNEL = 0x20, - PORT = 0x21, - END = 0x2F, - TEMPO = 0x51, - SMPTE = 0x54, - TIMESIG = 0x58, - KEYSIG = 0x59, - PROPRIETARY = 0x7F - }; - - smf( void ); - ~smf( void ); - - int open ( const char *name, int mode ); - - static void print_track_listing ( const char *name ); - - void write_meta_event ( byte_t type, int n ); - void write_meta_event ( byte_t type, const char *s ); - - void write_event ( const MIDI::midievent *e ); - void write_header ( int tracks ); - - void open_chunk ( const char *id ); - void close_chunk ( void ); - void open_track ( const char *name, int num ); - void close_track ( tick_t length ); - - void write_pattern_info ( const pattern *p ); - - void cue ( bool b ); - - list * read_track_events ( tick_t *length ); - - void write_phrase_info ( const phrase *p ); - - bool read_song_info( int *mode, int *phrases, int *patterns, char **name, char **notes ); - void write_song_info( int mode, int phrases, int patterns, const char *name, const char *notes ); - - void home ( void ); - void skip ( size_t l ); - void backup ( size_t l ); - - int next_track ( void ); - bool seek_track ( int n ); - char ** track_listing ( void ); - - char * read_cue_point ( void ); - int read_header ( void ); - char * read_text ( void ); - char * read_track_name ( void ); - bool read_phrase_info ( phrase *p ); - bool read_pattern_info ( pattern *p ); - - int format ( void ) const; - int tracks ( void ) const; - -}; diff --git a/sequencer/src/transport.C b/sequencer/src/transport.C deleted file mode 100644 index e00ab67..0000000 --- a/sequencer/src/transport.C +++ /dev/null @@ -1,220 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -#include -#include -#include - -#include "transport.H" -#include "common.h" -#include "const.h" - -extern jack_client_t *client; - -/* FIXME: use JackSyncCallback instead? (sync-callback) */ - -Transport transport; - -static volatile bool _done; - -/** callback for when we're Timebase Master, mostly taken from - * transport.c in Jack's example clients. */ -/* FIXME: there is a subtle interaction here between the tempo and - * JACK's buffer size. Inflating ticks_per_beat (as jack_transport - * does) diminishes the effect of this correlation, but does not - * eliminate it... This is caused by the accumulation of a precision - * error, and all timebase master routines I've examined appear to - * suffer from this same tempo distortion (and all use the magic - * number of 1920 ticks_per_beat in an attempt to reduce the magnitude - * of the error. Currently, we keep this behaviour. */ -void -Transport::timebase ( jack_transport_state_t, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void * ) -{ - - if ( new_pos || ! _done ) - { - pos->valid = JackPositionBBT; - pos->beats_per_bar = transport._master_beats_per_bar; - pos->ticks_per_beat = 1920.0; /* magic number means what? */ - pos->beat_type = transport._master_beat_type; - pos->beats_per_minute = transport._master_beats_per_minute; - - double wallclock = (double)pos->frame / (pos->frame_rate * 60); - - unsigned long abs_tick = wallclock * pos->beats_per_minute * pos->ticks_per_beat; - unsigned long abs_beat = abs_tick / pos->ticks_per_beat; - - pos->bar = abs_beat / pos->beats_per_bar; - pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; - pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); - pos->bar_start_tick = pos->bar * pos->beats_per_bar * pos->ticks_per_beat; - pos->bar++; - - _done = true; - } - else - { - pos->tick += nframes * pos->ticks_per_beat * pos->beats_per_minute / (pos->frame_rate * 60); - - while ( pos->tick >= pos->ticks_per_beat ) - { - pos->tick -= pos->ticks_per_beat; - - if ( ++pos->beat > pos->beats_per_bar ) - { - pos->beat = 1; - - ++pos->bar; - - pos->bar_start_tick += pos->beats_per_bar * pos->ticks_per_beat; - } - } - } -} - - -Transport::Transport ( void ) -{ - _master_beats_per_bar = 4; - _master_beat_type = 4; - _master_beats_per_minute = 120; - _done = false; -} - -void -Transport::poll ( void ) -{ - jack_transport_state_t ts; - jack_position_t pos; - - ts = jack_transport_query( client, &pos ); - - rolling = ts == JackTransportRolling; - - valid = pos.valid & JackPositionBBT; - - bar = pos.bar; - beat = pos.beat; - tick = pos.tick; - - /* bars and beats start at 1.. */ - pos.bar--; - pos.beat--; - - /* FIXME: these probably shouldn't be called from the RT - thread... Anyway, it happens infrequently. */ - if ( pos.beats_per_minute != beats_per_minute ) - signal_tempo_change( pos.beats_per_minute ); - - if ( pos.beats_per_bar != beats_per_bar ) - signal_bpb_change( pos.beats_per_bar ); - - if ( pos.beat_type != beat_type ) - signal_beat_change( pos.beat_type ); - - ticks_per_beat = pos.ticks_per_beat; - beats_per_bar = pos.beats_per_bar; - beat_type = pos.beat_type; - beats_per_minute = pos.beats_per_minute; - - frame = pos.frame; - frame_rate = pos.frame_rate; - - /* FIXME: this only needs to be calculated if bpm or framerate changes */ - { - const double frames_per_beat = frame_rate * 60 / beats_per_minute; - - frames_per_tick = frames_per_beat / (double)PPQN; - ticks_per_period = nframes / frames_per_tick; - } - - tick_t abs_tick = (pos.bar * pos.beats_per_bar + pos.beat) * pos.ticks_per_beat + pos.tick; -// tick_t abs_tick = pos.bar_start_tick + (pos.beat * pos.ticks_per_beat) + pos.tick; - - /* scale Jack's ticks to our ticks */ - - const double pulses_per_tick = PPQN / pos.ticks_per_beat; - - ticks = abs_tick * pulses_per_tick; - tick = tick * pulses_per_tick; - - ticks_per_beat = PPQN; -} - -void -Transport::start ( void ) -{ - MESSAGE( "Starting transport" ); - jack_transport_start( client ); -} - -void -Transport::stop ( void ) -{ - MESSAGE( "Stopping transport" ); - jack_transport_stop( client ); -} - -void -Transport::toggle ( void ) -{ - if ( rolling ) - stop(); - else - start(); -} - -void -Transport::locate ( tick_t ticks ) -{ - jack_nframes_t frame = trunc( ticks * transport.frames_per_tick ); - - MESSAGE( "Relocating transport to %f, %lu", ticks, frame ); - - jack_transport_locate( client, frame ); -} - -void -Transport::set_beats_per_minute ( double n ) -{ - _master_beats_per_minute = n; - _done = false; -} - -void -Transport::set_beats_per_bar ( int n ) -{ - if ( n < 2 ) - return; - - _master_beats_per_bar = n; - _done = false; -} - -void -Transport::set_beat_type ( int n ) -{ - if ( n < 4 ) - return; - - _master_beat_type = n; - _done = false; -} diff --git a/sequencer/src/transport.H b/sequencer/src/transport.H deleted file mode 100644 index 68d7584..0000000 --- a/sequencer/src/transport.H +++ /dev/null @@ -1,84 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -using namespace sigc; - -#include // just for tick_t - -#include - -typedef double playhead_t; - -class Transport : public trackable { - - double _master_beats_per_minute; - unsigned _master_beats_per_bar; - unsigned _master_beat_type; - -public: - - signal signal_tempo_change; - signal signal_bpb_change; - signal signal_beat_change; - - bool master; /* are we driving the transport? */ - bool rolling; - bool valid; - volatile bool recording; - - unsigned long bar; - unsigned beat; - unsigned tick; - - playhead_t ticks; - - unsigned beats_per_bar; - unsigned beat_type; - double ticks_per_beat; - double beats_per_minute; - - double ticks_per_period; - double frames_per_tick; - - double frame_rate; - - double frame; - double nframes; - - Transport ( void ); - - void poll ( void ); - void start ( void ); - void stop ( void ); - void toggle ( void ); - void locate ( tick_t ticks ); - - void set_beats_per_minute ( double n ); - void set_beats_per_bar ( int n ); - void set_beat_type ( int n ); - - static void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg ); - -}; - -extern Transport transport; diff --git a/sequencer/wscript b/sequencer/wscript deleted file mode 100644 index 0b7a28d..0000000 --- a/sequencer/wscript +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -import subprocess -import waflib.Options as Options -import string -import os - -# Version of this package (even if built as a child) -PACKAGE_VERSION = '1.9.5' - -# Variables for 'waf dist' -APPNAME = 'non-sequencer' -VERSION = PACKAGE_VERSION - -# Mandatory variables -top = '.' -out = 'build' - -def options(opt): - opt.load('compiler_c') - opt.load('compiler_cxx') - opt.load('gnu_dirs') - -def configure(conf): - conf.load('compiler_c') - conf.load('compiler_cxx') - conf.load('gnu_dirs') - - conf.check_cfg(package='sigc++-2.0', uselib_store='SIGCPP', - atleast_version='2.0.0', args="--cflags --libs", mandatory=True) - - conf.define('VERSION', PACKAGE_VERSION) - conf.define('SYSTEM_PATH', '/'.join( [ conf.env.DATADIR, APPNAME ] ) ) - conf.define('DOCUMENT_PATH', '/'.join( [ conf.env.DATADIR, 'doc' ] ) ) - conf.define('PIXMAP_PATH', '/'.join( [ conf.env.DATADIR, 'pixmaps' ] ) ) - - conf.write_config_header('config.h', remove=False) - - print('') - -def build(bld): - - libs = '' - - bld.program( source = ''' -src/NSM.C -src/NSM/Client.C -src/canvas.C -src/debug.C -src/grid.C -src/gui/event_edit.fl -src/gui/ui.fl -src/instrument.C -src/jack.C -src/main.C -src/mapping.C -src/pattern.C -src/phrase.C -src/scale.C -src/sequence.C -src/smf.C -src/transport.C -''', - target = 'non-sequencer', - includes = ['.', 'src', 'src/gui', '../FL', '../nonlib'], - use = ['nonlib', 'fl_widgets'], - uselib = [ 'JACK', 'SIGCPP', 'LIBLO', 'XLIB', 'NTK', 'NTK_IMAGES', 'PTHREAD'], - install_path = '${BINDIR}') - - bld( features = 'subst', - source = 'non-sequencer.desktop.in', - target = 'non-sequencer.desktop', - encoding = 'utf8', - install_path = "${DATADIR}" + '/applications', - BIN_PATH = bld.env.BINDIR ) - - bld.install_files('/'.join( [ '${DATADIR}', APPNAME, 'instruments'] ), bld.path.ant_glob('instruments/*')) - - start_dir = bld.path.find_dir( 'icons/hicolor' ) - - bld.install_files('${DATADIR}/icons/hicolor', start_dir.ant_glob('**/*.png'), - cwd=start_dir, relative_trick=True) - - bld.install_as('${DATADIR}/pixmaps/' + APPNAME + '/icon-256x256.png', 'icons/hicolor/256x256/apps/' + APPNAME + '.png') - - bld.install_files( '/'.join( [ '${DATADIR}/doc', APPNAME ] ), bld.path.ant_glob( 'doc/*.html doc/*.png' ) ) diff --git a/timeline/bin/import-ardour-session b/timeline/bin/import-ardour-session deleted file mode 100755 index 7640386..0000000 --- a/timeline/bin/import-ardour-session +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python2 - -# Copyright (C) 2013 Jonathan Moore Liles # -# # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the # -# Free Software Foundation; either version 2 of the License, or (at your # -# option) any later version. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with This program; see the file COPYING. If not,write to the Free Software # -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # - -import xml.etree.ElementTree as et -import random -import sys -import os -from datetime import date -import shutil - -if len(sys.argv) == 1: - print( "Usage: import-ardour-session [PATH_TO_ARDOUR_FILE] [NAME_OF_NON_TIMELINE_PROJECT]" ) - sys.exit( 1 ) - -Overwrite=False - -i = 1; - -if ( sys.argv[i] == "--overwrite" ): - Overwrite = True - i = i + 1 - -ArdourFilePath = sys.argv[i] -i = i + 1 -NonTimelineProjectPath = sys.argv[i] -i = i + 1 - -try: - os.makedirs( NonTimelineProjectPath ); - os.makedirs( NonTimelineProjectPath + "/sources"); -except: - if not Overwrite: - print( "Output path already exists!" ) - sys.exit( 1 ) - -try: - tree = et.parse( ArdourFilePath ); -except: - print( "Invalid XML input" ) - sys.exit( 1 ) - -root = tree.getroot(); - -Sources = {} -DiskStreams = {} - -print( "Gathering session info" ) -if root.tag != "Session": - print( "Not an Ardour session?" ) - sys.exit(1) - -print( "Ardour session file version is " + root.attrib["version"] ) -print( "This program is known to work with versions <= 3.0.1" ) - -ProjectName = root.attrib["name"] - -print( "Converting Ardour session \"" + ProjectName + "\" to Non Timeline format. Please be patient." ) - - -print( "Gathering sources." ) -for node in root.findall( "./Sources/Source" ): - Sources[node.attrib["id"]] = node; -# print( "\tFound source " + node.attrib["name"] ) - -print( "Gathering version 3 diskstreams." ) -for node in root.findall( "./Routes/Route/Diskstream" ): - DiskStreams[node.attrib["id"]] = node; - print( "\tFound diskstream " + node.attrib["name"] ) - -print( "Gathering version 2 diskstreams." ) -for node in root.findall( "./DiskStreams/AudioDiskstream" ): - DiskStreams[node.attrib["id"]] = node; -# print( "\tFound diskstream " + node.attrib["name"]; ) - - -print( "Gathering version 1 diskstreams." ) -for node in root.findall( "./DiskStreams/DiskStream" ): - DiskStreams[node.attrib["id"]] = node; -# print( "\tFound diskstream " + node.attrib["name"]; ) - -LoggableID = 1; - -def NewID(): - global LoggableID - ID="0x%x" % LoggableID - LoggableID = LoggableID + 1 - return ID - - -History = "{\n" - -print( "Processing tempo." ) - -for node in root.findall("./TempoMap/Tempo"): - TempoID = NewID() - History += ( "\tTempo_Point " + TempoID + " create :start 0 :tempo " + node.attrib["beats-per-minute"] + "\n") - -for node in root.findall("./TempoMap/Meter"): - TimeID = NewID() - try: - BPB = node.attrib["beats-per-bar"] - except: - BPB = node.attrib["divisions-per-bar"] - - History += ( "\tTime_Point " + TimeID + " create :start 0 :beats_per_bar " + BPB + " :beat_type " + node.attrib["note-type"] + "\n") - - -print( "Processing playlists." ) -for node in root.findall( "./Playlists/Playlist" ): - - try: - Track = DiskStreams[node.attrib["orig_diskstream_id"]] - except: - try: - Track = DiskStreams[node.attrib["orig-track-id"]] - except: - print( "\tSkipping playlist " + node.attrib["name"] + " for unknown diskstream" ) - continue - - - if node.attrib["name"] == Track.attrib["playlist"]: - print( "\tFound playlist " + node.attrib["name"] ) - - # for chan in range(0, int( Track.attrib["channels"] )): - TrackID = NewID() - SequenceID = NewID() - # if int(Track.attrib["channels"]) > 1: - # TrackName = Track.attrib["name"] + "-" + ( "%i" % chan ) - # else: - TrackName = Track.attrib["name"] - Channels = int(Track.attrib["channels"]) - - History += ( "\tTrack " + TrackID + " create :name \"" + TrackName + "\"" + ( " :sequence " + SequenceID ) + " :color " + ( "%i" % random.randint(256,123123123)) + ( " :inputs %i :outputs %i\n" % ( Channels, Channels ) ) ) - History += ( "\tAudio_Sequence " + SequenceID + " create :track " + TrackID + " :name \"" + node.attrib["name"] + "\"\n" ) - for n2 in node.findall("./Region"): - RegionID = NewID(); - - if ( int( Track.attrib["channels"] ) > 1 ): - - SourceList = [] - APath1 = os.path.dirname(ArdourFilePath) + "/sounds/" - APath2 = os.path.dirname(ArdourFilePath) + "/interchange/" + ProjectName + "/audiofiles/" - - for chan in range(0, int( Track.attrib["channels"] )): - SourceName = Sources[n2.attrib["source-" + ( "%i" % chan )]].attrib["name"] - - if os.path.exists( APath1 + SourceName): - SourceName = APath1 + SourceName - elif os.path.exists( APath2 + SourceName ): - SourceName = APath2 + SourceName - else: - print( "source not found!" ) - - SourceList.append( "'" + SourceName + "'" ); - - s1,s2,s3 = Sources[n2.attrib["source-0"]].attrib["name"].partition( '%' ) - - SourceName = s1 + ".wav" - OutputName = NonTimelineProjectPath + "/sources/" + SourceName - - if not os.path.exists( OutputName ): - print( "Combining multifile source into multichannel source" ) - os.system( "sox -S -M " + " ".join(SourceList) + " " + "'" + OutputName + "'" ) - - else: - SourceName = Sources[n2.attrib["source-0"]].attrib["name"]; - if not os.path.exists( NonTimelineProjectPath + "/sources/" + SourceName ): - print( "\t\tCopying source: " + SourceName ) - - try: - shutil.copy( os.path.dirname(ArdourFilePath) + "/interchange/" + ProjectName + "/audiofiles/" + SourceName, - NonTimelineProjectPath + "/sources/" ) - except: - shutil.copy( os.path.dirname(ArdourFilePath) + "/sounds/" + SourceName, - NonTimelineProjectPath + "/sources/" ) - - - History += ("\tAudio_Region " + RegionID + - " create :source \"" + SourceName + - "\" :start " + n2.attrib["position"] + - " :length " + n2.attrib["length"] + - " :offset " + n2.attrib["start"] + - " :sequence " + SequenceID + "\n") - else: - print( "\tSkipping inactive playlist" ) - -History += ("}\n") - -print( "Comitting to disk." ) - -with open( NonTimelineProjectPath + "/info", 'w' ) as InfoFile: - try: - SampleRate = root.attrib["sample-rate"] - except: - print( "Couldn't find sample rate... Using default." ) - SampleRate = "48000" - - InfoFile.write( "created by\n\tNon-Timeline 1.2.0\ncreated on\n\t" + date.today().ctime() + "\nversion\n\t2\nsample rate\n\t" + SampleRate + "\n" ) - -with open( NonTimelineProjectPath + "/history", 'w' ) as HistoryFile: - HistoryFile.write( History ) - -print( "Done. You've been freed. Go make music!" ) - diff --git a/timeline/bin/import-ardour-session_gui.fl b/timeline/bin/import-ardour-session_gui.fl deleted file mode 100644 index ad24c98..0000000 --- a/timeline/bin/import-ardour-session_gui.fl +++ /dev/null @@ -1,103 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.h} -code_name {.cxx} -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -Function {} {open -} { - code {UserInterface *ui = new UserInterface(); - -Fl_Double_Window *w = ui->make_window(); - -w->show(); - -Fl::run(); - -return 0;} {} -} - -class UserInterface {open -} { - Function {make_window()} {open - } { - Fl_Window main_window { - label {Import Ardour Session} open - xywh {610 468 395 310} type Double xclass {Non-Timeline} visible - } { - Fl_Box {} { - label {Non Timeline : Ardour Session Importer} - xywh {5 6 385 54} box ROUND_UP_BOX color 90 labelfont 1 labelsize 16 - } - Fl_Box {} { - label {This program will non-descrutively examine an existing Ardour 1, 2 or 3 format session file and replace the current Non Timeline project with the Tracks and Regions it finds. This program will only operate on a new (empty) Non Timeline project.} - xywh {5 66 385 128} box ROUND_UP_BOX align 128 - } - Fl_Return_Button {} { - label Import - callback {pid_t pid; -if ( ! (pid = fork()) ) -{ - - char *s; -// asprintf( &s, "xterm -into 0x%lx -e import-ardour-session --overwrite '%s' '%s'", fl_xid( main_window ), file_input->value(), getenv("PWD" )); - asprintf( &s, "import-ardour-session --overwrite '%s' '%s'", file_input->value(), getenv("PWD" )); - - exit( system( s ) ); -} - - -int status; - -while ( 0 == waitpid( pid, &status, WNOHANG ) ) -{ - Fl::wait(0.01); - - if ( progress->value() >= 100 ) - progress->value( 0 ); - else - progress->value( progress->value() + 5 ); - - progress->redraw(); -} - -if ( 0 == status ) - fl_message( "Import succesful. You've been freed. Go make music!" ); -else - fl_alert( "There was an error importing this session!" ); - -exit(0);} selected - xywh {270 270 115 30} - } - Fl_File_Input file_input { - label {Path to .ardour File:} - xywh {10 226 285 34} align 1 - } - Fl_Button {} { - label Browse - callback {file_input->value( fl_file_chooser( ".ardour file", "*.ardour", NULL, 0 ) );} - xywh {300 231 85 30} - } - Fl_Slider progress { - label {slider:} - xywh {15 272 245 27} type Horizontal color 48 selection_color 63 labeltype NO_LABEL align 18 maximum 100 deactivate - } - } - } -} diff --git a/timeline/bin/import-external-sources b/timeline/bin/import-external-sources deleted file mode 100755 index 34b39eb..0000000 --- a/timeline/bin/import-external-sources +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2008 Jonathan Moore Liles # -# # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the # -# Free Software Foundation; either version 2 of the License, or (at your # -# option) any later version. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with This program; see the file COPYING. If not,write to the Free Software # -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # - -## import-external-sources -# -# June 2008, Jonathan Moore Liles -# -# Simple script to scan a compacted Non-DAW project and copy external -# sources into the project directory. -# -# USAGE: -# -# $ import-external-sources ~/audio/'The Best Song Ever' - -DRY_RUN=no -ONLY_COMPACTED=no - -fatal () -{ - echo Error: "$1" - echo 'Aborting!' - cleanup - exit 1 -} - -cleanup () -{ - rm -f "${TEMP}/external-sources" -} - -import_sources () -{ - local FILE - while read FILE - do - if [ $DRY_RUN = yes ] - then - echo "Would import: ${FILE}" - else - echo "Importing source \"${FILE}\"..." - cp "${FILE}" sources - [ -f "${FILE}.peak" ] && cp "${FILE}.peak" sources - - ( echo "%s':source \"${FILE}\"':source \"${FILE##*/}\"'"; echo -e "\nwq" ) | - ed -s "history" - fi - done -} - -[ $# -gt 0 ] || fatal "Usage: $0 [--dry-run] path/to/project" - -if [ "$1" = --dry-run ] -then - DRY_RUN=yes - shift 1 -fi - -PROJECT="$1" - -cd "$PROJECT" || fatal "No such project" - -[ -f history ] && [ -f info ] || fatal "Not a Non-DAW project?" - -[ -f .lock ] && fatal "Project appears to be in use" - -if [ $ONLY_COMPACTED = yes ] -then - grep -v '\(^\{\|\}$\)\|create' history && fatal "Not a compacted project" -fi - -echo "Scanning \"${PROJECT}\"..." - -sed -n 's/^\s*Audio_Region .* create :source "\([^"]\+\)".*$/\1/; /^\//p' history | sort | uniq > "${TEMP}/external-sources" - -import_sources < "${TEMP}/external-sources" - -cleanup - -echo "Done." diff --git a/timeline/bin/remove-unused-sources b/timeline/bin/remove-unused-sources deleted file mode 100755 index 798a1c0..0000000 --- a/timeline/bin/remove-unused-sources +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2008 Jonathan Moore Liles # -# # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the # -# Free Software Foundation; either version 2 of the License, or (at your # -# option) any later version. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with This program; see the file COPYING. If not,write to the Free Software # -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # - -## remove-unused-sources -# -# April 2008, Jonathan Moore Liles -# -# Simple script to scan a compacted Non-DAW project and remove all -# unused sources from disk. -# -# USAGE: -# -# $ remove-unused-sources ~/audio/'The Best Song Ever' -# -# NOTES: -# -# This script will not ask for comfirmation! It will ruthlessly -# delete all unused sources! You have been warned. -# - -DRY_RUN= -ONLY_COMPACTED= -MOVE=1 - -fatal () -{ - echo Error: "$1" - echo 'Aborting!' - cleanup - exit 1 -} - -cleanup () -{ - rm -f "${TEMP}/all-sources" "${TEMP}/used-sources" -} - -set_diff () -{ - diff --new-line-format '' --old-line-format '%L' --unchanged-line-format '' "$1" "$2" -} - -remove_sources () -{ - local TOTAL=0 - local FILE - local SIZE - local PSIZE - while read FILE - do - - PSIZE=`stat -c '%s' "${FILE}.peak" 2>/dev/null` - SIZE=`stat -c '%s' "${FILE}" 2>/dev/null` - - PSIZE=${PSIZE:-0} - - if ! [ -f "${FILE}" ] - then - echo "Would remove \"${FILE}\", if it existed." - else - if [ "$DRY_RUN" = 1 ] - then - echo "Would remove: ${FILE}" - else - if [ "$MOVE" = 1 ] - then - echo "Moving unused source \"${FILE}\"..." - mv -f ./"${FILE}" ./"${FILE}".peak ../unused-sources - else - echo "Removing unused source \"${FILE}\"..." - rm -f ./"${FILE}" ./"${FILE}".peak - fi - fi - - TOTAL=$(( $TOTAL + $SIZE + $PSIZE )) - fi - - done - - echo "...Freeing a total of $(($TOTAL / ( 1024 * 1024 ) ))MB" -} - -usage () -{ - fatal "Usage: $0 [-n] [-c] [-m|-d] path/to/project" -} - - -while getopts "dmnc" o -do - case "$o" in - d) MOVE= ;; - m) MOVE=1 ;; - n) DRY_RUN=1 ;; - c) ONLY_COMPACTED=1 ;; - \?) usage ;; - *) echo "$o" && usage ;; - esac -done - -shift $(( $OPTIND - 1 )) -PROJECT="$1" - -[ $# -eq 1 ] || usage - -cd "$PROJECT" || fatal "No such project" - -[ -f history ] && [ -f info ] || fatal "Not a Non-DAW project?" - -[ -f .lock ] && fatal "Project appears to be in use" - -if [ "$ONLY_COMPACTED" = 1 ] -then - grep -v '\(^\{\|\}$\)\|create' history && fatal "Not a compacted project" -fi - -echo "Scanning \"${PROJECT}\"..." - -sed -n 's/^\s*Audio_Region.* :source "\([^"]\+\)".*$/\1/p' history | sort | uniq > "${TEMP}/used-sources" - -cd sources || fatal "Can't change to source directory" - -[ "$MOVE" = 1 ] && mkdir ../unused-sources 2>/dev/null - -ls -1 | grep -v '\.peak$' | sort > "${TEMP}/all-sources" - -set_diff "${TEMP}/all-sources" "${TEMP}/used-sources" | remove_sources - -cleanup - -echo "Done." diff --git a/timeline/doc/MANUAL.html b/timeline/doc/MANUAL.html deleted file mode 100644 index 9d2219d..0000000 --- a/timeline/doc/MANUAL.html +++ /dev/null @@ -1,410 +0,0 @@ - - - - - -Non Timeline User Manual - - - -
-

Non Timeline User Manual

-

-
-Jonathan Moore Liles <male@tuxfamily.org>
-
- -

-
- -

1. User Manual

-

1.1. The Timeline

-
- - - -
-Fig. 1.1. Timeline Editor -
fig. 1.1
-

-The Timeline is where you will add tracks, make captures, and arrange regions. -

-

-Before you can add anything to the timeline, you must create a new project (menu item Project/New) -

-
- - - -
-Fig. 1.2. New Project Dialog -
fig. 1.2
-

1.1.1. Display Options

-

-The display options, found in the Options/Display submenu may be adjusted to suit your needs. Set the color scheme, widget style, and other graphic options to your liking. These options are global and affect all projects. -

-

1.1.2. Navigation

-

1.1.2.1. Sequences

-

-A sequence is focused when you click on it. Focus can be moved back and forth between sequences with Tab and Shift-Tab. -

-

1.1.2.2. Playhead

-

-Shift+Left and Shift+Right move the playhead backward and forward one beat, while Ctrl+Shift+Left and Ctrl+Shift+Right move it by bars. -

-
1.1.2.2.1. Within A Sequence
-

-The focused sequence accepts additional movement commands with specific relevance. Ctrl+Left moves the playhead to the beginning of the current or previous object in the sequence. Ctrl+Right moves it to the beginning of the next object in the sequence. -

-

1.1.3. Cursors

-
- - - -
-Fig. 1.3. Cursor Strips -
fig. 1.3
-

-Active cursors are displayed the the cursor strip along the top of the timeline. The default cursors define regions of time. All cursors can be manipulated in their tracks by dragging with the mouse or other operations that apply to regions on the timeline. -

-

-Ctrl+RightClick will remove a cursor. -

-

1.1.3.1. Edit Cursor

-
- - - -
-Fig. 1.4. Edit Cursor -
fig. 1.4
-

-The edit cursor defines a region to apply an operation to. The edit cursor is also used to define the region other cursors, such as Punch and Playback, are created from. -

-

-Ctrl+[ moves the beginning of the edit cursor to the position of the playhead. Ctrl+] moves the end of the edit cursor to the position of the playhead. -

-

-The edit cursor ends can be set individually with the mouse by positioning the pointer over the desired location and pressing [ or ]. Alternatively, both may be set at once by holding the r key and left-click+dragging the selection rectangle. -

-

1.1.3.2. Playback Cursor

-

-

-Hitting Ctrl+Shift+L sets the playback cursor to the same dimensions and position as the Edit Cursor. -

-

1.1.3.3. Punch Cursors

-

-Punch Cursors define regions where recording will occur when recording in Punch Mode. -

-

-Hitting Ctrl+Shift+P defines a new Punch Cursor with the same dimensions and position as the Edit Cursor. -

-

-Any number of punch cursors may be defined. -

-

1.1.4. Projects

-
- - - -
-Fig. 1.5. Project Info Dialog -
fig. 1.5
-

-A Non Timeline project is a directory where Non Timeline keeps the journal, project specific settings, notes, some meta-data, and, last but not least, your audio sources. A project is completely self-contained. You can rename a project as simply as: -

-
-
-$ mv Project-A Project-B
-
-

-Non Timeline projects can refer to audio sources outside of the project directory--clips dropped onto the timeline from a file-manager, for instance. These are not copied into the project by default. This allows the efficient use of audio loop libraries, but introduces external dependencies. Beware that if you ever move, remove, or change one of these external sources, it will affect the Non Timeline projects referencing them. -

-
- - -
Note:To import all the external sources for a project, making it suitable for -distribution or archiving, use the `import-external-sources` script included -with the program. -
-
-

1.1.4.1. Settings

-

-Project specific settings are found in the Project/Settings submenu. -

-

1.1.5. Transport

-
- - - -
-Fig. 1.6. Transport Controls -
fig. 1.6
-

-The transport controls allow you to control the JACK transport from the Timeline Editor. Home moves the playhead to 0 and End moves it to the end of the project. Space toggles playback. -

-

1.1.6. Clocks

-
- - - -
-Fig. 1.7. Clocks -
fig. 1.7
-

-The clocks tell you precisely where the playhead is. There are several clock types which can be cycled through by left-clicking. The following clock types are available: -

-
  1. Hours Minutes Seconds -
  2. Timecode -
  3. Sample -
  4. Bar Beat Tick -

1.1.7. Tempo Map

-
- - - -
-Fig. 1.8. The Tempo Map -
fig. 1.8
-

-The tempo map serves a dual purpose. Firstly, it provides enough information about the musical structure of your project for Non Timeline to perform intelligent snapping and draw helpful measure lines. Secondly, the tempo map is communicated to other JACK clients at playback time via the JACK Timebase API, so that MIDI accompaniment can follow along to the tempo changes in your song. -

-

-Clicking on an empty part of the time or tempo sequences will prompt you for the parameters of a new time or tempo point to be inserted at that position. Hit Escape to cancel the insertion. Right-click on a time or tempo point to edit its value. Existing points can be dragged freely. -

-

1.1.8. Tracks

-
- - - -
-Fig. 1.9. A Track Header -
fig. 1.9
-

-Add a track to the timeline by pressing the A key. Right-clicking on the track header will bring up a context menu by which you can configure the number of channels used by this track. Click on the track name to change it. The Takes menu lists all the takes associated with a track. The circular record-enable button is used to arm a track for recording. Only armed tracks will be recorded onto when the master record-enable button on the transport is activated and the transport is started. The 'm' toggle button is mute, the 's' button is solo. Multiple tracks can be soloed at once. Shift+Mousewheel will adjust the track height. Remove a track by selecting 'Remove' from its context menu. -

-

1.1.8.1. Recording

-
- - - -
-Fig. 1.10. Recording onto a Track -
fig. 1.10
-

-To initiate recording, first arm some tracks by toggling their record buttons, then toggle the global record-enable button on the transport. Recording will begin when you press play. During recording, the timeline darkens and refuses normal input. Regions being captured are colored bright red. The viewport will automatically follow the playhead as the recording progresses. Recording stops when you stop the transport or toggle the global record-button. -

-

1.1.9. Sequences

-

-Sequence is the generic term used to describe all distinct sequences of objects on the timeline. -

-

1.1.10. Regions

-

-Regions are the most common object on the timeline. Each region represents some portion of an audio source placed at some position in time. Since Non Timeline is non-destructive, regions only represent the source--altering a region does not affect the audio source in any way. Deleting a region does not delete the source--as other regions may still refer to it. -

-
- - -
Note:If you decide, for whatever reason, that you no longer wish to retain unused -sources, run the `remove-unused-sources` script included with the program. -
-
-

-Try this one-liner to clean up many projects in parallel and reclaim disk space: -

-
-
-for i in ~/projects/*; do remove-unused-sources "$i" & done
-
-

1.1.10.1. Editing

-
1.1.10.1.1. Split
-

-Position the mouse pointer where you would like the region split and perform Shift+Middle-click. This will divide the region at the mouse pointer. -

-
1.1.10.1.2. Duplicate
-

-Drag a region (or selection) with the mousse while holding the Ctrl key to duplicate it. -

-
1.1.10.1.3. Delete
-

-Ctrl+Right-click removes a region or selection from the timeline. -

-
1.1.10.1.4. Trim
-

-Hold down Shift and click on part of a region with the left mouse button. This trims the region start to the position of the mouse pointer. Continue holding Shift and drag to continuously trim the region start point. Do the same with the right mouse button to trim the region end. -

-
1.1.10.1.5. Pan
-

-Hold Ctrl+Shift and drag the region. Instead of moving on the timeline, the region will remain stationary as the audio source behind it is panned forward or back. This operation is particularly useful in conjunction wiht looped regions. -

-
1.1.10.1.6. Normalize
-

-Hit N while a region is focused to normalize it (or Ctrl+Middle-click). Normalizing a region means automatically setting its gain as high as possible without exceeding the standard floating point audio dynamic range of +1 to -1 (corresponding to 0dBFS). Any peaks exceeding this range at this stage will appear in bright red. -

-
1.1.10.1.7. Fade
-
- - - -
-Fig. 1.11. A Region with Fades -
fig. 1.11
-

-Each region has fade in and out curves. Position the mouse pointer over the desired fade-in end location and hit F3 to set the fade-in duration. Position the mouse pointer over the desired fade-out start location and hit F4 to set the fade-out duration. Right click on a region to bring up its context menu, then choose the type of curve for each fade. The following curves are available: -

-
  1. Linear -
  2. Sigmoid -
  3. Logarithmic -
  4. Parabolic -
1.1.10.1.8. Loop
-
- - - -
-Fig. 1.12. Looped region -
fig. 1.12
-

-Instead of requiring you to duplicate a small region 100 times to achieve a looping effect, Non Timeline supports looping directly. First, adjust the region duration to cover the amount of time you would like it to loop for. Then, position the mouse pointer over the first place the loop should repeat (i.e. the first bar line after the start of the region) and hit L. This will set the loop point for this region, which will be indicated by two white arrows. At playback, the portion of the region before the loop point will loop for the duration of the region. -

-

1.1.11. Annotation

-
- - - -
-Fig. 1.13. Annotations -
fig. 1.13
-

-Add an annotation sequence to a track by right-clicking on the track header to bring up the context menu, and choosing Add annotation. Any number of annotation sequences may be attached to each track. Click on an empty space in the sequence to add a new annotation point. Right click on the annotation point to rename it. Hold down shift and drag with the right mouse button to create a new annotation region of a given duration. Again, right click to edit the text. Only the first line of annotation region text will be displayed on the timeline. Annotation regions are useful for containing lyrics or other cues which have a definite duration. Annotation points are more appropriately used to denote points of interest or change. -

-

1.1.12. Automation

-
- - - -
-Fig. 1.14. Control Sequence -
fig. 1.14
-

-Each track may have any number of control sequences attached to it. A control sequence comprises a series of points in time (X axis) and intensity (Y axis). Add a control sequence to a track by picking Add control from its context menu. A control sequence may be named by right clicking on it to bring up the context menu, then picking Rename. The output of a control sequence can be set to one of two modes Control Voltage (JACK) or Control Signal (OSC). -

-
- -
NOTE: -Since release 1.1.0, Control Signal is now the default output mode for Control Sequences. -If you have existing projects and wish to continue using Control Voltage output, -you must set the mode to Control Voltage manually. -
-
-

-Click anywhere on the control sequence to add a new control point. Control points can be dragged around and selected just like other objects on the timeline. They can even be part of the same selection as regions, permitting you to move regions and control points together in lock-step. -

-

1.1.12.1. Output Mode

-
1.1.12.1.1. Control Voltage
-

-Control Voltage is similar to control voltages generated by analog equipment. Setting the Control Sequence mode to Control Voltage will create a JACK output port whose contents simulate an analogue Control Voltage signal. This mode can be used to control anything that accepts CV style input. Useful targets include the Non-Mixer, and SpiralSynthModular. -

-
1.1.12.1.2. Control Signal
-

-The Control Signal mode uses a signal routing layer on top of the OSC protocol to intelligently and automatically discover and control any module parameter in Non-Mixer. The output of one Control Sequence may be connected to any number of Control Signal inputs available in Non-Mixer. -

-

-Control Signals are more efficient than Control Voltages when a large number of parameters are being automated. -

-
- - - -
-Fig. 1.15. Control Signal Connection -
fig. 1.15
-

1.1.12.2. Interpolation Mode

-
- - - -
-Fig. 1.16. Effect of Interpolation Mode -
fig. 1.16
-

-The interpolation mode controls how the relatively small number of Control Points is transformed into a continuously varying signal. The options are None and Linear. -

-

-When its Interpolation mode is set to None, a Control Sequence will output discrete jumps in value upon the playhead passing each Control Point. This can be useful when instantaneous changes in value are required, such as sudden muting, or changing the modes of plugins. -

-
- - diff --git a/timeline/doc/MANUAL.mu b/timeline/doc/MANUAL.mu deleted file mode 100644 index 36e5050..0000000 --- a/timeline/doc/MANUAL.mu +++ /dev/null @@ -1,363 +0,0 @@ - -! title Non Timeline User Manual -! author Jonathan Moore Liles #(email,male@tuxfamily.org) - --- Table Of Contents - -: User Manual - -:: The Timeline - -/ Timeline Editor -< tle.png - - The Timeline is where you will add tracks, make captures, and arrange regions. - - Before you can add anything to the timeline, you must create a new project - (menu item `Project\/New`) - -/ New Project Dialog -< new-project.png - -::: Display Options - - The display options, found in the `Options\/Display` submenu may be adjusted - to suit your needs. Set the color scheme, widget style, and other graphic - options to your liking. These options are global and affect all projects. - -::: Navigation - -:::: Sequences - - A sequence is focused when you click on it. Focus can be moved back and forth - between sequences with `Tab` and `Shift-Tab`. - -:::: Playhead - - `Shift+Left` and `Shift+Right` move the playhead backward and forward one - beat, while `Ctrl+Shift+Left` and `Ctrl+Shift+Right` move it by bars. - -::::: Within A Sequence - - The focused sequence accepts additional movement commands with specific - relevance. `Ctrl+Left` moves the playhead to the beginning of the current or - previous object in the sequence. `Ctrl+Right` moves it to the beginning of - the next object in the sequence. - -::: Cursors - -/ Cursor Strips -< cursors.png - - Active cursors are displayed the the cursor strip along the top of - the timeline. The default cursors define regions of time. All - cursors can be manipulated in their tracks by dragging with the - mouse or other operations that apply to regions on the timeline. - - `Ctrl+RightClick` will remove a cursor. - -:::: Edit Cursor - -/ Edit Cursor -< range.png - - The edit cursor defines a region to apply an operation to. The edit - cursor is also used to define the region other cursors, such as - Punch and Playback, are created from. - - `Ctrl+[` moves the beginning of the edit cursor to the position of - the playhead. `Ctrl+]` moves the end of the edit cursor to the - position of the playhead. - - The edit cursor ends can be set individually with the mouse by - positioning the pointer over the desired location and pressing `[` - or `]`. Alternatively, both may be set at once by holding the `r` - key and left-click+dragging the selection rectangle. - -:::: Playback Cursor - - The Playback Cursor defines the start and stop of playback, - affecting the action of the Home and End transport buttons. Setting - the menu option 'Options/Behavior/Transport/Loop Playback' will - result in playback looping over the region defined by the Playback - Cursor. - - Hitting `Ctrl+Shift+L` sets the playback cursor to the same - dimensions and position as the Edit Cursor. - -:::: Punch Cursors - - Punch Cursors define regions where recording will occur when - recording in Punch Mode. - - Hitting `Ctrl+Shift+P` defines a new Punch Cursor with the same - dimensions and position as the Edit Cursor. - - Any number of punch cursors may be defined. - -::: Projects - -/ Project Info Dialog -< project-info.png - - A Non Timeline project is a directory where Non Timeline keeps the journal, project - specific settings, notes, some meta-data, and, last but not least, your audio - sources. A project is completely self-contained. You can rename a project as - simply as: - -> $ mv Project-A Project-B - - Non Timeline projects can refer to audio sources outside of the project - directory--clips dropped onto the timeline from a file-manager, for instance. - These are not copied into the project by default. This allows the efficient - use of audio loop libraries, but introduces external dependencies. Beware - that if you ever move, remove, or change one of these external sources, it - will affect the Non Timeline projects referencing them. - -/ Note: -{ To import all the external sources for a project, making it suitable for -{ distribution or archiving, use the `import-external-sources` script included -{ with the program. - -:::: Settings - - Project specific settings are found in the `Project\/Settings` submenu. - -::: Transport - -/ Transport Controls -< transport.png - - The transport controls allow you to control the JACK transport from the - Timeline Editor. `Home` moves the playhead to 0 and `End` moves it to the - end of the project. `Space` toggles playback. - -::: Clocks - -/ Clocks -< clocks.png - - The clocks tell you precisely where the playhead is. There are several clock - types which can be cycled through by left-clicking. The following clock types - are available: - -+ Hours Minutes Seconds -+ Timecode -+ Sample -+ Bar Beat Tick - -::: Tempo Map - -/ The Tempo Map -< tempomap.png - - The tempo map serves a dual purpose. Firstly, it provides enough information - about the musical structure of your project for Non Timeline to perform - intelligent snapping and draw helpful measure lines. Secondly, the tempo map - is communicated to other JACK clients at playback time via the JACK Timebase - API, so that MIDI accompaniment can follow along to the tempo changes in your - song. - - Clicking on an empty part of the time or tempo sequences will prompt you for - the parameters of a new time or tempo point to be inserted at that position. - Hit `Escape` to cancel the insertion. Right-click on a time or tempo point to - edit its value. Existing points can be dragged freely. - -::: Tracks - -/ A Track Header -< track-header.png - - Add a track to the timeline by pressing the `A` key. Right-clicking on the - track header will bring up a context menu by which you can configure the - number of channels used by this track. Click on the track name to change it. - The `T`akes menu lists all the takes associated with a track. The circular - record-enable button is used to arm a track for recording. Only armed tracks - will be recorded onto when the master record-enable button on the transport - is activated and the transport is started. The 'm' toggle button is mute, the - 's' button is solo. Multiple tracks can be soloed at once. `Shift+Mousewheel` - will adjust the track height. Remove a track by selecting 'Remove' from its - context menu. - -:::: Recording - -/ Recording onto a Track -< recording.png - - To initiate recording, first arm some tracks by toggling their record - buttons, then toggle the global record-enable button on the transport. - Recording will begin when you press play. During recording, the timeline - darkens and refuses normal input. Regions being captured are colored bright - red. The viewport will automatically follow the playhead as the recording - progresses. Recording stops when you stop the transport or toggle the global - record-button. - -::: Sequences - - Sequence is the generic term used to describe all distinct sequences of - objects on the timeline. - -::: Regions - - Regions are the most common object on the timeline. Each region represents - some portion of an audio source placed at some position in time. Since - Non Timeline is non-destructive, regions only *represent* the source--altering a - region does not affect the audio source in any way. Deleting a region does - not delete the source--as other regions may still refer to it. - -/ Note: -{ If you decide, for whatever reason, that you no longer wish to retain unused -{ sources, run the `remove-unused-sources` script included with the program. - - Try this one-liner to clean up many projects in parallel and reclaim disk space: - -> for i in ~/projects/*; do remove-unused-sources "$i" & done - -:::: Editing - -::::: Split - - Position the mouse pointer where you would like the region split and perform - `Shift+Middle-click`. This will divide the region at the mouse pointer. - -::::: Duplicate - - Drag a region (or selection) with the mousse while holding the `Ctrl` key to - duplicate it. - -::::: Delete - - `Ctrl+Right-click` removes a region or selection from the timeline. - -::::: Trim - - Hold down `Shift` and click on part of a region with the left mouse button. - This trims the region start to the position of the mouse pointer. Continue - holding `Shift` and drag to continuously trim the region start point. Do the - same with the right mouse button to trim the region end. - -::::: Pan - - Hold `Ctrl+Shift` and drag the region. Instead of moving on the timeline, the - region will remain stationary as the audio source /behind/ it is panned - forward or back. This operation is particularly useful in conjunction wiht - looped regions. - -::::: Normalize - - Hit `N` while a region is focused to normalize it (or `Ctrl+Middle-click`). - Normalizing a region means automatically setting its gain as high as possible - without exceeding the standard floating point audio dynamic range of +1 to -1 - (corresponding to 0dBFS). Any peaks exceeding this range at this stage will - appear in bright red. - -::::: Fade - -/ A Region with Fades -< fade-in-out.png - - Each region has fade in and out curves. Position the mouse pointer over the - desired fade-in end location and hit `F3` to set the fade-in duration. - Position the mouse pointer over the desired fade-out start location and hit - `F4` to set the fade-out duration. Right click on a region to bring up its - context menu, then choose the type of curve for each fade. The following - curves are available: - -+ Linear -+ Sigmoid -+ Logarithmic -+ Parabolic - -::::: Loop - -/ Looped region -< looping.png - - Instead of requiring you to duplicate a small region 100 times to achieve a - looping effect, Non Timeline supports looping directly. First, adjust the region - duration to cover the amount of time you would like it to loop for. Then, - position the mouse pointer over the first place the loop should repeat (i.e. - the first bar line after the start of the region) and hit `L`. This will set - the loop point for this region, which will be indicated by two white arrows. - At playback, the portion of the region before the loop point will loop for - the duration of the region. - -::: Annotation - -/ Annotations -< annotations.png - - Add an annotation sequence to a track by right-clicking on the track header - to bring up the context menu, and choosing /Add annotation/. Any number of - annotation sequences may be attached to each track. Click on an empty space - in the sequence to add a new annotation point. Right click on the annotation - point to rename it. Hold down shift and drag with the right mouse button to - create a new annotation region of a given duration. Again, right click to - edit the text. Only the first line of annotation region text will be - displayed on the timeline. Annotation regions are useful for containing - lyrics or other cues which have a definite duration. Annotation points are - more appropriately used to denote points of interest or change. - -::: Automation - -/ Control Sequence -< automation.png - - Each track may have any number of control sequences attached to - it. A control sequence comprises a series of points in time (X axis) - and intensity (Y axis). Add a control sequence to a track by picking - /Add control/ from its context menu. A control sequence may be named - by right clicking on it to bring up the context menu, then picking - /Rename/. The output of a control sequence can be set to one of two - modes /Control Voltage \(JACK\)/ or /Control Signal \(OSC\)/. - -{ NOTE: -{ Since release 1.1.0, Control Signal is now the default output mode for Control Sequences. -{ If you have existing projects and wish to continue using Control Voltage output, -{ you must set the mode to Control Voltage manually. - - Click anywhere on the control sequence to add a new control point. Control - points can be dragged around and selected just like other objects on the - timeline. They can even be part of the same selection as regions, permitting - you to move regions and control points together in lock-step. - -:::: Output Mode - -::::: Control Voltage - - /Control Voltage/ is similar to control voltages generated by analog - equipment. Setting the Control Sequence mode to Control Voltage will - create a JACK output port whose contents simulate an analogue - Control Voltage signal. This mode can be used to control anything - that accepts CV style input. Useful targets include the Non-Mixer, - and SpiralSynthModular. - -::::: Control Signal - - The /Control Signal/ mode uses a signal routing layer on top of the - OSC protocol to intelligently and automatically discover and control - any module parameter in Non-Mixer. The output of one Control - Sequence may be connected to any number of Control Signal inputs - available in Non-Mixer. - - Control Signals are more efficient than Control Voltages when a - large number of parameters are being automated. - -/ Control Signal Connection -< control-signals.png - -:::: Interpolation Mode - -/ Effect of Interpolation Mode -< control-points.png - - The interpolation mode controls how the relatively small number of - Control Points is transformed into a continuously varying - signal. The options are /None/ and /Linear/. - - When its Interpolation mode is set to /None/, a Control Sequence - will output discrete jumps in value upon the playhead passing each - Control Point. This can be useful when instantaneous changes in - value are required, such as sudden muting, or changing the modes of - plugins. - diff --git a/timeline/doc/Makefile b/timeline/doc/Makefile deleted file mode 100644 index c20d132..0000000 --- a/timeline/doc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -SRCS=$(wildcard *.mu) - -OBJS=$(SRCS:.mu=.html) - -%.html: %.mu - @ echo Mupping $<... - @ mup.wrapper html $< - -.PHONY: all clean - -all: $(OBJS) - -upload: all - @ rsync -L mup.css MANUAL.html *.png ssh.tuxfamily.org:/home/non/non-daw.tuxfamily.org-web/htdocs - -install: - @ install -d "$(DESTDIR)$(DOCUMENT_PATH)"/non-daw - @ cp $(OBJS) *.png mup.css ../../COPYING "$(DESTDIR)$(DOCUMENT_PATH)"/non-daw -# @ ln -sf $(PIXMAP_PATH)/logo.png $(DOCUMENT_PATH) - -clean: - rm -f $(OBJS) diff --git a/timeline/doc/annotations.png b/timeline/doc/annotations.png deleted file mode 100644 index 57f65e6..0000000 Binary files a/timeline/doc/annotations.png and /dev/null differ diff --git a/timeline/doc/automation.png b/timeline/doc/automation.png deleted file mode 100644 index b6a0c7f..0000000 Binary files a/timeline/doc/automation.png and /dev/null differ diff --git a/timeline/doc/clocks.png b/timeline/doc/clocks.png deleted file mode 100644 index fb22b79..0000000 Binary files a/timeline/doc/clocks.png and /dev/null differ diff --git a/timeline/doc/control-points.png b/timeline/doc/control-points.png deleted file mode 100644 index 8ea09c3..0000000 Binary files a/timeline/doc/control-points.png and /dev/null differ diff --git a/timeline/doc/control-signals.png b/timeline/doc/control-signals.png deleted file mode 100644 index b0d54ba..0000000 Binary files a/timeline/doc/control-signals.png and /dev/null differ diff --git a/timeline/doc/cursors.png b/timeline/doc/cursors.png deleted file mode 100644 index 782c5d5..0000000 Binary files a/timeline/doc/cursors.png and /dev/null differ diff --git a/timeline/doc/fade-in-out.png b/timeline/doc/fade-in-out.png deleted file mode 100644 index 27b28cb..0000000 Binary files a/timeline/doc/fade-in-out.png and /dev/null differ diff --git a/timeline/doc/icon.png b/timeline/doc/icon.png deleted file mode 120000 index 9450c05..0000000 --- a/timeline/doc/icon.png +++ /dev/null @@ -1 +0,0 @@ -../icons/hicolor/256x256/apps/non-timeline.png \ No newline at end of file diff --git a/timeline/doc/looping.png b/timeline/doc/looping.png deleted file mode 100644 index f9dcd44..0000000 Binary files a/timeline/doc/looping.png and /dev/null differ diff --git a/timeline/doc/mup.css b/timeline/doc/mup.css deleted file mode 100644 index 10aceae..0000000 --- a/timeline/doc/mup.css +++ /dev/null @@ -1,461 +0,0 @@ - -/* Example CSS Style for MUP */ - -body -{ - font: normal normal 14pt "Helvetica", sans-serif; -/* background: url("http://non.tuxfamily.org/background-pattern.png") fixed; */ - background-color: #121212; color: lightgray; padding: 0; margin: 0; -} - -a:link { - color: white; -} -a:visited { - color: olive; -} -a:active { - color: white; -} -a:link:hover { - text-decoration: underline; -} - -/* #(url) */ -a.ext:link { - color: red; - text-decoration: none; - border-bottom: dashed silver 1; -} -a.ext:visited { - color: darkred; - border-bottom: dashed silver 1; - text-decoration: none; -} - -/* #(ref) */ -a.int:link { - border-bottom: dashed silver 0.15em; -} -a.int:link:hover { - text-decoration: none; - color: white; -} - -/* - a[href^="#"]:link { - border-bottom: dashed silver 0.15em; - } - a[href^="#"]:link:hover { - text-decoration: none; - color: white; - } - */ - -p:contains("Warning:") { - background: #d00; - color: white; - border: dotted gray 0.5em; - display: block; -} - -/* First letter of first paragraph of every chapter */ -/* - h1 + p:first-letter { - text-transform: uppercase; - float: left; - line-height: 0.8em; - font-size: 350%; - font-family: Serif; - letter-spacing: 0; - margin-right: 0.1em; - margin-top: 0.1em; - border: solid gray 1px; - padding: 1px; - color: #d00; - text-shadow: #666 3px 3px 3px; - } - */ -/* First paragraph of every chapter */ -/* - h1 + p { - text-indent: 0; - } - */ - -/* cover */ -#cover * { - background: transparent; -} -#cover { - position: relative; -/* background: #da0;*/ - background: #555; - color: #aaa; - text-align: center; - margin: 0; - padding: 0.5em; - border-top: 4px solid black; - border-bottom: 4px solid black; -} -#cover h1, #cover h3 { - text-shadow: #222 0.2em 0.2em 0.2em; - color: white; - border: none; - letter-spacing: 0.2em; - line-height: 0.8em; - margin-left: 2em; - margin-right: 2em; -} -#cover h1:before, #cover h1:after { -/* content: "::"; */ - font-size: 300%; - color: black; -} -#cover h1:before { - position: absolute; - top: 0.2em; - left: 0.1em; -} -#cover h1:after { - position: absolute; - top: 0.2em; - right: 0.1em; -} -#cover hr { - display: none; -} - -hr:first-child { - display: none; -} - -hr { - height: 0.2em; - background: #555; - color: #555; - margin-left: 0.5em; -} - -#cover a:visited { - color: black; -} - -/* endnote */ -#endnote { - color: black; -} - -/* TOC */ -#toc { - position: relative; -} -#toc hr { -} -#toc h1 { -} -#toc ul { - font-size: 125%; - font-weight: bold; - margin-bottom: 1em; -} -#toc ul ul { - font-size: 90%; - font-weight: normal; - margin-bottom: 0; -} -#toc li { - list-style: none; - -} -#toc a:link { - border-bottom: 0; -} - -/* */ -#body { - position: relative; - margin: 0 auto; - padding: 0.5em; - max-width: 900px; - background-color: #1c1c1c; -} -/* ;, : */ -h1 { - color: #fff; - border-bottom: solid #444 0.1em; - text-shadow: 1px 1px 2px #000; - -} -/* ::, :::, ::::, :::::, :::::: */ -h2, h3, h4, h5, h6 { - color: #fff; - text-shadow: 1px 1px 2px #000; - -} - -/* tables, figures */ -.fig caption { - color: gray; - text-align: center; - /* Required for Mozilla */ - margin: auto; -} -.fig table { - border: none; - margin: auto; -/* border-collapse: collapse; */ -} -/* / */ -.fig.table th { - border: none; - background: gray; - color: black; -} -/* [ */ -.fig.table td { - border: none; - background: silver; - color: black; - padding-left: 1em; - padding-right: 1em; - padding-top: 0.2em; - padding-bottom: 0.2em; -} -/* < */ - -.fig.image table { - border: none; - background: transparent; - max-width: 100%; -} -.fig.image tr, .fig.image td { - border: none; - background: transparent; - padding: 0; -} - -.fig.image img -{ - max-width: 900px; -} - -/* */ -p { - margin-right: 2%; - text-align: justify; - text-indent: 1em; -} -/* > */ -.example * -{ - background: transparent; -} -.example table -{ - margin: 0; - padding: 0; - table-layout: fixed; - width: 100%; - caption-side: top; - overflow: auto; -} -.example caption -{ - caption-side: top; - -} -.example { -} -.example p { - display: inline; - margin: 0; - padding: 0; - text-align: center; -} -.example pre { - margin-top: 0; - font-family: Monospace; - padding: 1em; - border: solid 1px black; - background: #222; - color: white; - display: block; - overflow: auto; - /* Every browser should support border radii */ -/* -moz-border-radius: 0.5em; - border-radius: 0.5em; */ -} -/* " */ -/* - .quote:before { - float: left; - font-size: 500%; - content: "\201C"; - } - */ -/* - blockquote:after { - content: "\201D"; - }*/ -.quote blockquote { - padding: 0.5em; - margin-left: 0.5em; - font-family: Serif; - border-left: solid 0.4em gray; - /* background: #333; */ - color: white; -} -/* ^ */ -small { -/* - color: silver; - font-size: 50%; - */ -} -.footnote p { - color: silver; - margin: 0; -} - -/* Popup footnotes */ -.footnote p { - display: none; -} -.footnote p:target { - display: block; - overflow: auto; - position: fixed; - left: auto; - bottom: 0; - right: 0; - max-width: 50%; - border: solid 0.3em white; - -moz-border-radius: 0.5em; - background: black; - padding: 0.2em; -} - -/* { */ -.admonition * { - background: transparent; - color: white; -} -.admonition dl -{ - display: table; - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition dt -{ - display: table-cell; - vertical-align: center; - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} -.admonition dd -{ - padding-left: 0.4em; - display: table-cell; - width: 100%; - text-align: justify; -} - -.admonition table -{ - margin: 0; - padding: 0; - background: #333; - border: dotted black 0.3em; - width: 90% - margin-top: 0.5em; - margin-bottom: 0.5em; -} -.admonition td { - width: 100%; - text-align: justify; -} -.admonition td:first-child:contains("Warning:") { - background: #900; -} -.admonition td:first-child:contains("Caution:") { - background: #960; -} -.admonition td:first-child:contains("Note:") { - background: #690; -} -.admonition td:first-child { - border-right: solid silver 0.4em; - font-weight: bold; - font-size: 115%; - font-family: Serif; - background: gray; - width: 0; - text-shadow: black 0.15em 0.15em 0.15em; -} - - -/* #(b) */ -/* b { color: olive; } */ -/* #(c) */ -tt { - color: #7f0; -} -/* ! keywords ... */ -p em { - color: gray; - font-style: normal; - font-weight: bold; -} - -/* *, + */ -/* Bullet, numbe */ -li { - color: #f0f; -} -/* Text */ -li span, li p { - color: white; -} -li p { - color: red; - display: block; -} -ul { - list-style-type: square; -} -dl { - margin-left: 2%; - margin-top: 1em; -} -/* = */ -dt { - background: #181818; - padding: 0.2em; - font-variant: small-caps; - font-weight: bold; - color: #f0f; -} -dd { - color: white; - text-align: justify; - margin-right: 5%; -} -dt a:link, dt a:visited { - color: #f0f; -} -dt a:link:hover { - color: silver; - text-decoration: underline; -} diff --git a/timeline/doc/new-project.png b/timeline/doc/new-project.png deleted file mode 100644 index 4f0aa6c..0000000 Binary files a/timeline/doc/new-project.png and /dev/null differ diff --git a/timeline/doc/project-info.png b/timeline/doc/project-info.png deleted file mode 100644 index aca00fe..0000000 Binary files a/timeline/doc/project-info.png and /dev/null differ diff --git a/timeline/doc/range.png b/timeline/doc/range.png deleted file mode 100644 index 9aabfff..0000000 Binary files a/timeline/doc/range.png and /dev/null differ diff --git a/timeline/doc/recording.png b/timeline/doc/recording.png deleted file mode 100644 index 5a50448..0000000 Binary files a/timeline/doc/recording.png and /dev/null differ diff --git a/timeline/doc/tempomap.png b/timeline/doc/tempomap.png deleted file mode 100644 index 40aab88..0000000 Binary files a/timeline/doc/tempomap.png and /dev/null differ diff --git a/timeline/doc/tle.png b/timeline/doc/tle.png deleted file mode 100644 index 5589e29..0000000 Binary files a/timeline/doc/tle.png and /dev/null differ diff --git a/timeline/doc/track-header.png b/timeline/doc/track-header.png deleted file mode 100644 index 16f89c2..0000000 Binary files a/timeline/doc/track-header.png and /dev/null differ diff --git a/timeline/doc/transport.png b/timeline/doc/transport.png deleted file mode 100644 index 29cdd87..0000000 Binary files a/timeline/doc/transport.png and /dev/null differ diff --git a/timeline/icons/hicolor/128x128/apps/non-timeline.png b/timeline/icons/hicolor/128x128/apps/non-timeline.png deleted file mode 100644 index 31a0cf0..0000000 Binary files a/timeline/icons/hicolor/128x128/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/16x16/apps/non-timeline.png b/timeline/icons/hicolor/16x16/apps/non-timeline.png deleted file mode 100644 index c7ae573..0000000 Binary files a/timeline/icons/hicolor/16x16/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/192x192/apps/non-timeline.png b/timeline/icons/hicolor/192x192/apps/non-timeline.png deleted file mode 100644 index a080632..0000000 Binary files a/timeline/icons/hicolor/192x192/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/256x256/apps/non-timeline.png b/timeline/icons/hicolor/256x256/apps/non-timeline.png deleted file mode 100644 index 36f9431..0000000 Binary files a/timeline/icons/hicolor/256x256/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/32x32/apps/non-timeline.png b/timeline/icons/hicolor/32x32/apps/non-timeline.png deleted file mode 100644 index 0398e1e..0000000 Binary files a/timeline/icons/hicolor/32x32/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/36x36/apps/non-timeline.png b/timeline/icons/hicolor/36x36/apps/non-timeline.png deleted file mode 100644 index dc95873..0000000 Binary files a/timeline/icons/hicolor/36x36/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/48x48/apps/non-timeline.png b/timeline/icons/hicolor/48x48/apps/non-timeline.png deleted file mode 100644 index ca70cda..0000000 Binary files a/timeline/icons/hicolor/48x48/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/512x512/apps/non-timeline.png b/timeline/icons/hicolor/512x512/apps/non-timeline.png deleted file mode 100644 index 1b33b18..0000000 Binary files a/timeline/icons/hicolor/512x512/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/64x64/apps/non-timeline.png b/timeline/icons/hicolor/64x64/apps/non-timeline.png deleted file mode 100644 index 5b88078..0000000 Binary files a/timeline/icons/hicolor/64x64/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/72x72/apps/non-timeline.png b/timeline/icons/hicolor/72x72/apps/non-timeline.png deleted file mode 100644 index d186caf..0000000 Binary files a/timeline/icons/hicolor/72x72/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/96x96/apps/non-timeline.png b/timeline/icons/hicolor/96x96/apps/non-timeline.png deleted file mode 100644 index 2bc5bb4..0000000 Binary files a/timeline/icons/hicolor/96x96/apps/non-timeline.png and /dev/null differ diff --git a/timeline/icons/hicolor/scalable/apps/non-timeline.svg b/timeline/icons/hicolor/scalable/apps/non-timeline.svg deleted file mode 100644 index 24ab03c..0000000 --- a/timeline/icons/hicolor/scalable/apps/non-timeline.svg +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/timeline/icons/icon-16x16.xpm b/timeline/icons/icon-16x16.xpm deleted file mode 100644 index a813e41..0000000 --- a/timeline/icons/icon-16x16.xpm +++ /dev/null @@ -1,774 +0,0 @@ -/* XPM */ -static char *icon_16x16[] = { -/* columns rows colors chars-per-pixel */ -"512 512 256 2 ", -" c #0001019A0001", -". c #09E2064602B5", -"X c #06870889067A", -"o c #0A1808C20522", -"O c #0B3C0CA50A0A", -"+ c #12F50C2A0541", -"@ c #18940EBE051A", -"# c #10100E0E0909", -"$ c #0E8810460DE5", -"% c #19B0106B0642", -"& c #124811620CC9", -"* c #188E11350975", -"= c #12E714E912E7", -"- c #187816F71131", -"; c #170219041702", -": c #1A0B198314D9", -"> c #1B301D1D1AF0", -", c #25F318CC0AFE", -"< c #30301D1D0808", -"1 c #22821D9E1434", -"2 c #1EC520C71EC5", -"3 c #2F2F20200F0F", -"4 c #36E122A20D22", -"5 c #3C6F25250C73", -"6 c #276A23BF1B96", -"7 c #369325821336", -"8 c #386729861847", -"9 c #22A6243E21AB", -"0 c #28E029042525", -"q c #2B8A2D8C2B8A", -"w c #32322DAE2424", -"e c #2E3230342E32", -"r c #38A633DE2A67", -"t c #32B734933258", -"y c #373239343732", -"u c #3AF63BD53A18", -"i c #430A27D20BB6", -"p c #430728DD0DA4", -"a c #54DC32050E3B", -"s c #44442CC513DD", -"d c #44592EEF182D", -"f c #4B8B305013FC", -"g c #444430B11BB5", -"h c #4A7D34DB1DAA", -"j c #526633B413D0", -"k c #5B2036991139", -"l c #5BC6390E14AA", -"z c #523536B719B6", -"x c #528B38B91D73", -"c c #5B433C4C1BD4", -"v c #64553CF51356", -"b c #63463ECD18C3", -"n c #439037842842", -"m c #527D3AD72185", -"M c #59A33E5121EE", -"N c #42223D5D3595", -"B c #3F3F40403F3F", -"V c #6767406B16C1", -"C c #6D6D4067115A", -"Z c #642441161C3C", -"A c #6B8544831BB3", -"S c #756B4540121A", -"D c #792D4875157F", -"F c #7A474C101B82", -"G c #507B41C23086", -"H c #5454474736B7", -"J c #63CE445923CE", -"K c #687446462274", -"L c #6D4549892414", -"P c #6666490429E5", -"I c #6BCB4C222AEF", -"U c #74344C7322BC", -"Y c #79394EE422CD", -"T c #7A3F512925D7", -"R c #7ABF53E72B7A", -"E c #68B1532E39CC", -"W c #7AEA57773272", -"Q c #443A453B443A", -"! c #4AA0499F4545", -"~ c #4C354D314C25", -"^ c #55554D86425F", -"/ c #53D451514C4C", -"( c #543155325431", -") c #585858835681", -"_ c #5B655C665B65", -"` c #65A5583846A6", -"' c #66665E5E5414", -"] c #5F5F60605F5F", -"[ c #767661E24909", -"{ c #666662625A5A", -"} c #76CC68125580", -"| c #61AA62AB61AA", -" . c #676768686767", -".. c #6B786C796B78", -"X. c #75DC6E076363", -"o. c #7777717167A7", -"O. c #732D742E732D", -"+. c #777778787777", -"@. c #7B207C217B20", -"#. c #82D84EF918C3", -"$. c #88AD50E31684", -"%. c #8CBC561B1D63", -"&. c #945458D91ADB", -"*. c #9BB95CF31BB2", -"=. c #A1A15F5F1919", -"-. c #ADE6672E1C1C", -";. c #881857F324C0", -":. c #89265BD22BD3", -">. c #9B705F3420A1", -",. c #87FE5E5E31F7", -"<. c #8F8F61612F2F", -"1. c #9BB861F024DE", -"2. c #9494620C2BD6", -"3. c #9C0965712BCA", -"4. c #88B3617E37A9", -"5. c #99886879348A", -"6. c #B0BE71052E2E", -"7. c #A1F46C7D3413", -"8. c #C2C2729D1F1F", -"9. c #C1DD746223B6", -"0. c #C8487A8E28FD", -"q. c #C3C37DE734F9", -"w. c #97926E694141", -"e. c #924972A94F06", -"r. c #886B733A593C", -"t. c #A3A87674473B", -"y. c #AB007B254848", -"u. c #ABAB7E174D4D", -"i. c #87877A7A6893", -"p. c #7F7F80807F7F", -"a. c #FBFB81A902B4", -"s. c #FBFB85FA0B80", -"d. c #FBFB8A0A1394", -"f. c #FBFB8E191B1B", -"g. c #FBFB90901F1F", -"h. c #DD2E84F52870", -"j. c #C8A981FC37FA", -"k. c #CBDE855F3BB7", -"l. c #D1D184843434", -"z. c #DE188B3C3333", -"x. c #DE478E4239FE", -"c. c #ED638D1627C5", -"v. c #EFCA90FE2DC0", -"b. c #F67691912626", -"n. c #FBFB92552333", -"m. c #FBF696042B82", -"M. c #E6A68D8D2FF0", -"N. c #EF93946F33A1", -"B. c #E8BD9393398F", -"V. c #FBF89A8E343D", -"C. c #F42F983D37CE", -"Z. c #FC4C9E623B55", -"A. c #FCFCA0A03F3F", -"S. c #B8B880804646", -"D. c #BC7585774B92", -"F. c #B792883F5530", -"G. c #98988239661D", -"H. c #878782027777", -"J. c #98988A0A76CC", -"K. c #AEB891A57017", -"L. c #C771892047B0", -"P. c #CCCC89DF4360", -"I. c #C32E89894C90", -"U. c #D4D48E8E44C5", -"Y. c #DD6496874B5A", -"T. c #C2978BEF520B", -"R. c #CC4492195481", -"E. c #DA4E995353B0", -"W. c #EA1C9C354A17", -"Q. c #F1F19D6444EF", -"!. c #FCF9A28B43A7", -"~. c #F168A1F74DD6", -"^. c #FCF7A6694B66", -"/. c #FCFCA8A84F4F", -"(. c #ED42A24C52FD", -"). c #F107A4BB53DF", -"_. c #FCFAAAA453CB", -"`. c #F2CFA891597C", -"'. c #FCF8AE585B43", -"]. c #FCFCB0B05F5F", -"[. c #C3189CF272C8", -"{. c #D252A54573F4", -"}. c #E905AC016A14", -"|. c #F2F2AD3D6333", -" X c #F7A1B1B167BD", -".X c #FCF9B29D63C8", -"XX c #FCF9B6B06BA9", -"oX c #FCFCB8B86F19", -"OX c #FCFCBB3B73F4", -"+X c #FD8BBEA17B5E", -"@X c #FDFDC0C07F7F", -"#X c #83B084B183B0", -"$X c #878788888787", -"%X c #8B198C1A8B19", -"&X c #8F8F90908F8F", -"*X c #989892128706", -"=X c #94A495A594A4", -"-X c #9B5D9C5E9B5D", -";X c #AA8D9B9B87C0", -":X c #9F9FA0A09F9F", -">X c #A9A9A2A29757", -",X c #BABAA8BF91C0", -" t BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX-X B BXLXLXLXLXLX) +.LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXq X 0 BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2XX e BXLXLXLXLXLX.. | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X X X X X ", -" X X $ mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXnX1X( t X X X > -XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX4X 2XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2X2 X = %XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXnX X X X X ", -" ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXO. X X %XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX2 B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX$X X X X X @.LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt 9 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX-XX X X X X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX! X X X ", -" X X X &XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX:X X X X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX_ p.LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX4X :XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXO. X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX5XO X X X %XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX$X X X X X X X ", -" X X X X X nXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2 X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX:X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt 2 BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2X :XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ $ NXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXnX X X X X ", -" X X X X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX1X X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmX X BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX5X X X X -XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXX NXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmX X X $XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX= X ", -" X X X X t LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X ..LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXO 9 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXp. X X ) LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2 $ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX&X X X ! LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt X ", -" ! LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X Q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX2 X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt X 2 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX.. X X X X 2 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ X X X X X ", -" X X X X X X _ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt X X X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe Q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ X X X X 9 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX_ X $ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX_ X X X X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X X X X X ", -" X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -"X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX0 X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX/ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X X X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXu ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -"X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X X X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX/ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -"X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX/ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X X X X X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X u LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXu ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX/ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX/ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X X X ", -" X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| ", -"X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X ", -" X X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -"X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X X X X X ", -" X X X X X X X X .LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX . X X ", -" X X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X t LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X > LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X X X X ", -" X X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X X X X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X X y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X ", -" X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X / LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ y LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX( LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX] X X X ", -"X X X X X X | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ X X ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X X X ", -" X _ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX0 X X 0 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe ~ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXQ X X X 2 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX! X t LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X X X X X X X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX_ X X X X ", -" X X X X X ! LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX; ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX9 B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X X X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB 9 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB X mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X X X X ", -" X X X B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX X LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX= X B LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXO. X X X ) LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXt $ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXe X X 5XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXy X X X X X X ", -" X X X X 0 LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmX X NXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX ; LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX4X X X =XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX; BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX= 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX9 X X X X ", -" X X X X X mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX:X X X X X X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmXX X #XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXO X X X X X X X X ", -" X X X +.LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX~ X ! LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X BXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXnXX X X X X X 5XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmXX X e LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmX4X:Xp.q ; O.-X:X .$ e $X:X4XmXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXq X nXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX; X X -XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX2 X X X ", -" X X X X X X X X _ LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXe X X X X q LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXB %XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX| e NXLXLXLXLXmXe | LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXp. t LXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX) X X X X = NXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX| X X X ", -" X X 0 mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX ..LXLXLXLXLXLXLXLX=X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXnX9 ; nXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXNXq X X X X 1XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBXt X X ", -" X X X e mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX4X= X X X X X = 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX5X> X X ; 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXNX O.LXLXLXLXLXLXLXLX&X 4XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLX:X= X X > 5XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXnX9 X X -XLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXmXe X X X X X ", -" X X X X X ; 4XLXLXLXLX:X= Q mXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXLXBX:X] O 9 O.4XLXLXLXLXLXLXLXLXLXLX4Xp.e X X X X = | 2XBXLXLXLXLXLXLXLXLXLX5X$Xy X X X X X X X ", -" X X ; y ( ] ....] ! 9 X X X X X X X X = e ~ | ....| / q X X e ! ) ..........................................................B X y | | q $ Q ..........................................................) Q t X X $ t / ] ....] ~ e X X X O q ! _ ....| ( e $ X X X ", -" X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -"X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -" X X X X X X X X X X X X X X X X X X X X ", -"X X X X X X X X X X X X X X X X X X X X X X X X X X X X ", -"~ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X / ", -"UXMX( X X X X X X X X X X X X X X X X X X / MXUX", -"UXUXUXnX~ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ^ nXUXUXUX", -"UXUXUXUXUX0XB X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X B 5XUXUXUXUXUX", -"UXUXUXUXUXUXUX3Xt X X X X X X X X X X X X X X X X X X X X X X X X X X y 3XUXUXUXUXUXUXUX", -"UXUXUXUXUXUXUXUXUX3Xe X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X r 3XUXUXUXUXUXUXUXUXUX", -"UXUXUXUXUXUXUXUXUXUXUX>X0 X X X X X X X X X X X X X X X 0 X9 X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 9 >XIXUXIXUXIXUXUXIXUXUXIXUXIX", -"UXIXIXUXUXIXUXIXIXUXIXUXIXUXIX*X2 X X X X X X X X X X X X X X X X X 2 *XIXIXUXIXUXIXUXIXIXUXIXIXIXUXIX", -"IXIXUXIXIXUXUXIXUXIXUXIXUXIXUXIXPX*X: X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X ; *XPXUXIXUXIXUXIXUXIXUXUXIXUXIXUXIXUX", -"UXIXUXIXUXIXIXUXIXUXUXIXIXIXIXUXUXUXGXH.= X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X $ H.PXIXIXIXUXIXUXIXUXIXUXIXUXUXIXIXUXUXIX", -"IXIXIXIXIXIXIXIXIXIXIXIXUXIXIXIXIXIXIXUXGXH.$ X X X X X X X X X X X X X X X X X X X X X X X X X X $ H.GXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIX", -"IXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXFXo.O X X X X X X X X X X X X X X X X X X X X X X X X X o.FXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIX", -"IXIXIXIXIXIXIXKXIXIXIXIXKXIXIXIXIXIXKXIXKXIXIXIXFXo.X X X X X X X X X X X X X X X X X X X X X X X X X X o.FXIXIXIXIXKXIXIXIXIXIXIXIXIXIXKXIXKXIXIXIXKXIXIXIX", -"IXIXIXIXIXIXIXIXKXIXKXIXIXIXKXIXIXIXIXIXIXIXIXIXIXIXVX{ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X { VXIXIXKXIXIXIXIXIXKXIXKXIXIXKXIXIXIXIXIXIXIXIXIXIXKXIX", -"KXKXIXKXKXIXKXIXIXIXKXIXKXIXIXIXIXKXKXIXIXKXIXKXKXIXKXKXMX) X X X X X X X X X X X X X X X X X { VXKXIXKXIXIXIXIXKXIXKXIXIXKXIXIXKXIXKXKXIXIXKXKXIXKXIXKXIX", -"KXIXKXIXKXKXIXKXKXKXIXKXKXKXIXKXKXKXIXKXKXIXKXIXIXKXIXKXKXKXdX/ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X / dXKXIXKXKXIXKXKXKXIXKXIXKXIXKXKXKXKXIXKXIXKXIXIXKXIXKXKXIXKXIX", -"KXKXKXIXIXKXKXKXIXKXKXKXKXIXKXKXKXKXKXKXIXKXKXKXKXKXKXIXKXKXKXKX0X! X X X X X X X X X X X X X X X X X X X X ! 0XKXIXIXKXKXKXKXKXKXKXKXKXKXKXKXKXKXIXKXKXKXIXKXKXKXKXKXKXKXKXKXKX", -"KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXIXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX0XN X X X X X X X X X X X X X X X X X X X X X N 0XKXKXKXKXKXKXIXKXKXKXIXKXKXKXKXKXIXKXIXKXKXKXKXKXKXKXKXKXKXIXKXKXKXKX", -"KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXJX3Xy X X X X X X X X X X X X X X X X X X X X X X X X X X X t 3XKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKX", -"KXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXKXJXKXKXKXKXKXKXKXKXKXJXKXKXJXKXKXKXKXKXKXKX3Xq X X X X X X X X X X X X X X X X X X X X X X X X X X X w 3XKXKXKXKXKXJXKXKXJXKXJXKXKXJXKXKXJXKXJXKXKXJXJXKXKXJXKXJXKXKXJXKXKXKXJXKXKXJX", -"JXKXJXJXJXJXJXJXJXKXJXJXJXKXJXJXJXKXKXJXJXJXJXJXJXJXKXJXJXKXKXJXKXJXJXJXJXJXKXJX>X6 X X X X X X X X X X X X X X X X X X X X 0 >XJXJXKXJXJXJXKXJXJXKXJXKXKXKXJXKXJXKXJXKXKXKXJXKXKXJXJXKXKXJXJXKXKXJXJXKXKXJXJXKX", -"JXJXJXKXKXJXJXKXJXKXKXJXJXKXJXJXKXJXJXJXJXKXJXJXKXKXJXKXJXKXJXKXKXJXJXJXKXKXJXJXKXJX>X6 X X X X X X X X X X X X 6 >XJXKXKXKXJXKXKXKXJXKXJXKXKXJXJXKXKXJXJXKXKXJXJXKXKXJXJXKXJXKXJXKXJXJXJXKXJXJXJXKXKXJX", -"JXKXJXKXJXJXKXJXJXJXJXKXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXKXJXJXJXJXKXJXJXJXJXKXJXJXJXJXGX*X> X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X : *XHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJXJXJXKXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXJXGX*X- X X X X X X X X X X X X X X X X X X X X ; J.GXJXJXJXJXJXJXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXJXKXJXJXJXJXJXJXJXJXJXJXJXKXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXAXH.= X X X X X X X X X X X X X X X X X X X X X X X X X X X = i.GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXAXH.& X X X X X X X X X X X X X X X X X X X X X X X X X X X $ H.AXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXHXJXJXHXJXJXJXJXJXJXHXJXJXJXJXJXJXJXJXJXHXJXJXJXJXJXJXJXJXHXJXJXJXJXHXJXJXJXJXHXJXHXJXJXJXJXJXVXo.O X X X X X X X X X X X X X X X X X X X X X X X X O o.VXJXJXJXJXJXJXJXJXJXJXJXHXJXJXJXHXJXJXHXHXJXJXJXJXJXJXJXHXJXJXJXJXHXJXJXJXJXJXJXJXJXHXJXHXJXJXJXJXJXJXJX", -"HXJXJXJXJXJXJXJXHXJXJXJXHXJXJXJXHXJXJXJXHXJXJXJXJXJXJXHXJXJXJXHXHXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJXHXJXHXJXVXX.o X X X X X X X X X X X X X X X X X.VXHXJXJXHXJXHXJXJXJXJXHXJXJXHXJXJXHXHXJXJXJXJXJXJXHXJXJXHXJXJXJXJXJXJXJXJXHXJXJXJXHXHXJXJXJXJXJXJXJXHXJXJXHX", -"JXHXHXJXHXHXHXHXJXJXHXJXJXHXHXJXJXJXHXHXJXJXHXHXJXHXJXHXJXHXHXJXJXJXHXJXJXHXHXJXHXHXHXJXHXHXJXJXHXJXJXJXHXJXHXzX{ . X X X X X X X X X X X X X X X X X X X X X X X X X X X . { zXJXHXJXHXJXJXHXJXHXJXHXJXHXHXJXJXHXHXJXJXJXHXJXJXHXJXHXHXJXHXJXHXJXHXHXHXHXJXHXHXJXHXJXJXJXHXHXHXHXJXHXHXJXHXJX", -"HXHXJXHXHXJXJXHXHXHXHXHXHXHXJXHXHXHXHXJXHXHXHXJXHXHXJXJXHXJXHXJXJXHXHXJXHXHXJXJXHXJXHXHXHXJXHXHXJXJXHXHXJXHXHXJXJXdX{ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X { dXHXJXHXHXJXJXHXHXJXHXJXHXHXHXJXJXHXHXJXJXHXHXHXHXHXHXHXHXJXJXHXHXJXJXHXHXJXJXHXHXJXHXJXJXHXHXJXHXJXJXHXJXHXHXJXHXJX", -"JXHXHXJXJXHXHXJXJXHXJXJXJXHXHXJXHXJXHXJXHXJXJXHXHXJXHXHXHXHXJXHXHXHXJXHXHXJXHXHXJXHXJXHXJXHXJXHXHXHXJXHXHXHXJXHXHXHXJXsX/ X X X X X X X X X X X X X X X X X X X X X / dXJXJXJXHXHXJXHXHXHXJXHXJXHXHXJXJXHXHXJXJXHXHXJXJXHXJXJXHXJXJXHXHXHXJXHXHXJXHXJXHXJXJXHXHXHXHXJXHXHXHXJXHXJXHXJXHXHXJXHX", -"JXHXHXHXHXHXHXJXHXHXJXHXJXHXHXJXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXJXJXHXHXJXHXHXJXHXHXHXHXHXJXHXHXJXHX0X! X X X X X X X X X X X X X X X X X X X X X X X X X / sXHXJXHXHXHXHXJXHXHXJXHXJXHXHXHXJXHXHXHXHXHXHXHXHXJXHXHXJXHXJXHXHXJXHXJXHXHXHXHXHXHXHXJXHXHXJXHXHXJXHXHXJXHXJXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXJXHXHXJXJXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXDX0XN X X X X X X X X X X X X X X X X X X N 0XHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXHXHXJX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXDXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJX,Xr X X X X X X X X X X X X X X X X X X r 3XHXDXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXJXDX3Xr X X X X X X X X X X X X X X X X X X X r 3XDXDXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXDXHXHXHXHXHX", -"HXHXHXHXHXHXHXHXHXDXHXHXHXHXDXHXHXDXHXHXHXHXHXHXHXHXHXDXDXHXHXHXHXHXHXDXHXDXHXHXHXHXHXHXHXHXHXDXHXDXHXHXHXHXHXHXHXHXHXDXHXHXHXHXHXHXHXDXHX;X0 X X X X X X X X X X X X X X X X X X 0 ;XDXHXHXHXDXHXHXDXHXHXHXDXHXDXHXHXHXHXHXHXHXHXHXHXDXHXHXDXHXDXHXHXHXHXHXHXHXHXHXHXHXHXHXDXHXDXHXHXHXHXHXHXHXHXHXHXDXHXHXHXHXHXHXHXHXHXHXHXHX", -"HXDXHXDXDXHXDXHXHXHXHXDXDXHXDXHXHXHXHXDXHXDXDXHXDXHXDXHXHXHXDXHXDXHXDXHXHXHXHXDXHXDXDXHXDXHXDXHXHXHXHXDXHXDXDXHXDXHXDXHXDXHXDXHXDXHXDXHXDXHXDX;X9 X X X X X X X X X X X X X X X X X X X 6 ;XHXHXHXDXHXHXHXHXDXHXHXHXDXHXHXHXHXDXHXDXHXDXHXDXDXHXHXHXDXHXHXHXHXDXHXDXHXDXHXDXHXHXDXDXHXDXHXHXHXHXDXHXDXDXHXDXHXDXHXDXHXDXHXHXDXDXHXDXDXHXDX", -"HXDXDXHXHXDXHXDXDXDXDXHXDXHXDXHXHXDXDXHXDXDXHXHXDXHXHXDXHXDXDXHXDXHXHXDXHXDXDXHXDXDXHXHXDXHXHXDXHXDXDXHXDXDXHXDXDXHXHXDXHXDXDXHXDXHXHXDXHXDXDXHXSXJ.> X X X X X X X X X X X X X X X X : J.HXDXDXDXDXDXHXDXDXDXDXDXHXDXDXDXHXDXHXHXDXDXHXHXDXHXDXDXHXDXDXDXHXDXHXHXDXDXHXHXDXHXDXDXHXHXDXDXHXHXDXDXHXDXDXHXHXDXHXHXDXHXDXDXHXDXDXHXHXHXDXDXHX", -"DXHXDXDXDXHXDXHXDXHXHXDXDXDXHXDXDXDXHXDXDXHXDXDXHXDXDXHXDXHXDXDXHXDXDXHXDXDXHXDXDXHXDXDXHXDXHXDXDXDXHXDXDXHXDXHXHXDXDXHXDXHXDXDXHXDXHXDXDXHXDXDXHXDXAXJ.: X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X : J.AXDXHXHXDXHXHXHXDXDXHXDXHXDXHXDXHXDXHXDXDXDXDXHXDXDXDXDXHXHXDXDXHXDXHXDXDXDXHXDXDXDXDXDXHXHXDXDXDXHXDXDXHXDXDXDXHXDXDXHXDXHXDXDXHXDXDXDXHXDXDXDXHXDXDX", -"DXDXDXDXDXHXDXDXHXDXDXDXDXHXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXHXDXHXDXDXDXDXDXHXDXHXHXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXHXDXDXAXH.& X X X X X X X X X X X X X X X X X X X X X X $ H.CXHXHXDXDXDXDXDXDXHXDXDXDXDXDXHXDXDXDXDXDXDXHXDXDXDXDXDXDXDXDXHXDXDXDXDXDXDXHXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXHXHXDXDXDXDXDXDXDXDXHXDXHXDXDXDXDXDXDXDXDX", -"DXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXxXH.& X X X X X X X X X X X X X X X X X X X X X $ H.bXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDX", -"DXDXDXDXDXDXDXDXDXSXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXSXDXDXSXDXDXDXDXSXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXzXo.O X X X X X X X X X X X X X X X X X X X O X.xXDXZXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXSXDXDXDXDXDXDXDXDX", -"DXDXDXDXSXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXSXDXDXDXSXDXSXDXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXSXDXDXSXDXSXSXzXX.O X X X X X X X X X X X X X X X X X X O o.zXSXSXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXDXSXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXDXDXSXDXDXDXDXDXDXDXSXDXDXDXDXDXDXDXDXDXDX", -"SXDXDXDXDXSXSXSXSXDXSXDXDXDXSXDXSXDXSXDXSXDXSXDXDXSXSXDXDXDXDXSXSXDXDXDXSXDXSXSXSXDXDXSXDXDXSXDXDXDXSXDXDXSXDXDXDXSXSXDXDXSXSXSXDXDXDXSXSXDXDXSXDXSXDXSXDXDXDXSXSXSXSXDXzX' X X X X X X X X X X X X X X X { fXDXSXSXSXSXDXDXSXDXSXDXDXSXDXSXDXSXSXSXSXSXDXSXDXSXDXSXDXSXSXSXDXSXDXSXDXSXDXDXDXSXSXDXDXDXSXSXDXSXDXDXSXDXDXDXSXSXSXDXDXSXSXDXDXSXSXSXDXSXDXDXDXDXSXSXSXDXDXDXSXDXDXSXDX", -"SXSXSXSXSXDXSXSXSXSXDXSXSXSXSXSXSXSXDXSXDXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXDXSXSXSXSXSXSXSXSXDXSXSXSXSXDXSXSXSXDXSXSXSXSXSXDXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXsX' X X X X X X X X X X X X X X X X X X X X X ' fXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXDXSXSXSXSXSXDXSXSXDXSXSXDXSXSXSXSXDXSXDXSXSXSXSXSXSXSXSXDXSXSXSXSXDXSXDXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXDXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXsX^ X X X X X X X X X X X X X X X X X X X X X X X ^ sXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXsX^ X X X X X X X X X X X X X X X X X X X X X X X X X X X ^ sXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX7XB X X X X X X X X X X X X X X X X X X X X X X X X X X N ,XSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXZXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSX", -"SXSXSXSXZXSXSXZXSXZXSXSXSXSXSXZXZXSXSXZXSXZXSXSXSXSXSXZXSXZXSXZXSXSXSXZXZXSXSXSXSXZXSXSXSXZXZXSXSXSXSXbXZXSXSXZXSXSXZXSXSXZXSXZXSXSXSXZXSXZXSXZXZXSXZXSXSXZXSXSXZXSXSXSXSXZXSXSXZXSXSXZXZXSX,Xr X X X X X X X X X X X X X X X X X N ,XSXSXbXSXSXSXSXbXSXSXZXSXSXSXSXZXZXSXSXSXSXZXZXSXSXZXZXSXSXSXSXSXZXSXSXZXSXSXSXSXSXSXZXSXSXZXSXSXZXSXSXZXSXSXSXZXZXSXSXSXZXSXSXSXSXZXZXSXSXZXSXSXZXSXSXSXSXSXSXSXSXZXSXSXZXSXSXZXSXSXSXZXZXSX", -"SXZXZXSXZXSXZXSXZXSXSXZXSXSXSXZXSXSXZXSXZXSXSXZXSXSXSXZXSXSXZXSXSXSXZXSXZXSXSXSXZXSXSXZXSXZXSXZXbXSXSXSXSXSXSXSXZXSXSXSXSXSXSXZXSXSXSXZXSXSXZXSXSXSXSXSXZXSXZXSXZXSXSXSXZXSXSXZXSXSXSXZXSXSXZXSX,Xw X X X X X X X X X X X X X X X X X X r ,XSXZXSXZXSXSXbXSXSXSXSXbXSXSXZXSXZXSXSXSXZXSXZXSXSXSXZXSXSXSXSXSXZXSXSXSXZXSXZXSXSXZXSXSXSXZXSXSXZXSXSXSXSXSXZXSXSXSXZXSXZXSXSXZXZXSXZXSXSXZXSXSXZXSXSXSXZXZXSXZXSXSXSXZXSXZXSXSXSXZXSXZXSXZXSXZX", -"ZXSXZXZXSXZXSXZXSXZXSXZXZXZXZXSXZXZXSXZXSXZXSXZXZXZXSXZXZXSXZXSXZXZXSXZXSXZXZXZXSXZXZXSXZXSXZXSXSXSXbXZXSXbXZXSXZXSXZXZXZXSXZXSXZXZXSXZXZXSXZXSXZXZXZXSXZXSXZXZXSXZXZXZXSXZXSXZXZXZXSXZXZXZXSXSXSXZX;X6 X X X X X X X X X X X X X 6 ;XZXSXZXSXZXSXSXbXSXSXbXbXSXSXZXZXSXSXSXZXZXZXZXSXZXSXZXSXZXSXZXZXZXZXZXZXZXZXSXSXZXZXSXZXZXZXSXZXZXSXZXZXZXZXZXZXSXZXZXSXZXSXZXZXSXZXZXSXSXZXZXSXZXSXSXZXZXZXZXSXZXSXZXZXSXZXSXZXZXZXSXZXZXSXZXSXZXSX", -"SXZXZXSXZXZXSXZXSXZXSXSXZXZXSXZXSXZXSXZXSXSXZXSXZXSXZXZXSXZXSXZXZXZXZXSXZXZXZXSXSXZXSXSXZXSXSXZXSXZXZXZXZXZXZXDXZXSXZXZXSXZXSXZXZXSXZXSXZXSXZXSXSXZXZXSXZXZXSXZXSXZXZXSXZXZXSXZXSXZXSXSXZXSXSXZXSXZXSXZX;X2 X X X X X X X X X X X X X X X X X X X X X X X 2 ;XbXZXSXZXSXbXSXZXSXbXSXZXZXSXZXZXSXZXZXZXSXZXZXSXZXSXZXZXZXDXZXDXDXZXDXZXSXSXZXSXSXZXSXSXZXSXZXZXDXZXDXSXSXZXSXSXZXZXSXZXSXSXZXZXZXZXSXSXZXSXSXZXSXZXZXSXSXZXZXSXZXSXSXZXZXZXSXZXZXSXZXZXSXZXZXSXZXZXSXZX", -"SXZXZXSXZXSXSXZXZXSXZXZXZXSXZXSXZXZXZXZXZXZXZXZXZXSXSXZXZXSXZXSXZXSXSXZXZXSXSXZXZXZXZXZXZXZXZXZXSXZXZXSXZXDXZXZXZXSXSXZXSXZXZXSXZXZXZXSXSXbXSXZXZXSXSXZXZXSXZXSXZXZXSXZXZXSXSXZXZXZXZXZXZXZXZXZXZXSXZXSXZXbXJ.: X X X X X X X X X X X X X X X X X X : J.ZXZXZXSXSXZXZXSXZXSXZXSXZXSXSXZXZXSXZXSXSXZXZXSXZXZXZXZXSXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXSXZXSXZXZXZXSXSXZXZXZXZXZXZXSXZXSXZXZXZXSXZXZXZXZXZXSXSXZXZXSXSXZXZXSXZXZXSXZXZXSXSXZX", -"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXSXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXSXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXSXZXZXSXbXbXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXSXZXZXZXZXZXSXZXZXZXZXZXZXSXZXbXJ.- X X X X X X X X X ; J.bXSXZXZXZXZXZXZXSXbXSXbXZXZXSXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXSXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXSXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXSXZXZXSXZXZXZXZXZXZX", -"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXxXH.& X X X X X X X X X X X # H.xXZXZXZXZXZXZXZXZXZXbXSXbXSXZXZXbXZXZXZXZXZXZXZXZXZXZXZXbXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZX", -"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXbXbXSXbXbXSXbXZXZXZXZXZXZXbXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXxXi.$ X X X X X X X X X X X # H.jXbXZXZXSXbXbXSXZXZXZXZXSXbXbXbXbXSXbXSXZXZXZXZXZXZXZXZXZXSXbXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXSXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZX", -"bXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXZXZXZXbXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXZXZXZXZXZXbXZXbXZXZXZXZXZXbXZXbXbXSXbXSXbXbXSXZXZXZXZXZXZXZXbXZXZXZXZXZXZXZXZXbXZXZXZXZXbXZXZXZXZXZXZXZXbXZXZXZXZXZXZXZXjXX.O X X X X X X X X X X X X X X X X X X X X X X X X X O X.xXZXZXZXZXZXbXSXbXZXZXZXZXZXbXSXSXbXZXbXZXZXZXZXbXZXZXZXZXZXbXZXbXbXZXZXZXZXZXZXZXZXZXZXbXZXbXZXZXZXbXZXZXZXZXZXbXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXZXZXZXZXZXbXbXZXZXZXbXZXZXZXZXZXZXZXZXbX", -"ZXbXbXZXZXZXbXbXZXbXZXbXbXZXZXbXbXZXZXZXZXZXbXZXZXZXZXZXZXZXbXZXbXZXZXbXZXbXbXZXZXbXbXZXbXZXZXbXZXbXbXZXZXZXZXbXZXZXbXZXbXZXZXZXbXZXSXbXbXbXbXbXZXZXZXZXbXZXSXbXbXZXZXbXbXZXZXZXZXZXbXZXZXbXZXZXbXZXZXbXbXZXbXZXZXbXZXbXbXZXZXfXX.o X X X X X X X X X X X X X X X X X X X X X X } fXZXbXZXbXZXZXZXbXbXbXZXZXZXbXZXbXbXbXbXbXSXZXbXZXZXZXZXZXZXZXbXbXbXbXSXZXbXbXZXbXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXbXZXZXZXbXZXbXZXZXbXZXbXbXZXZXbXZXZXZXZXbXZXbXbXZXZXZXbXZXZXZXZXbXZXZXbXZXbXZXbXbXZXbXZXbXZXbXZXbXZXZXZXZXZXZXbX", -"bXZXZXbXbXbXbXZXZXbXbXZXbXbXbXZXZXbXvXZXvXZXbXbXbXZXbXbXbXbXZXbXbXbXZXbXbXZXbXbXbXZXbXZXbXbXbXZXZXbXZXbXbXbXbXZXbXZXbXbXZXbXbXbXbXbXbXbXbXSXbXbXbXbXbXZXbXbXbXbXbXbXbXZXbXZXbXbXbXbXZXbXZXbXbXZXbXbXbXZXbXZXbXbXZXbXbXZXbXbXbXZXbXfX' X X X X X X X X X X X X ' fXbXbXbXZXbXbXbXbXbXbXbXZXbXbXbXbXbXbXbXSXbXbXbXbXZXbXbXbXZXbXbXbXZXSXbXbXbXbXZXbXZXbXbXZXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXZXbXbXZXbXZXbXbXZXbXbXZXbXZXbXvXZXbXZXbXZXbXvXZXbXbXbXbXbXZXbXZXbXbXZXbXZXZXbXbXZXZXbXZXbXbXbXbXbXbXbXZXbX", -"bXbXZXbXZXbXZXZXbXbXbXZXbXZXbXbXbXbXbXZXZXbXZXZXbXbXZXbXbXbXZXZXZXZXbXbXbXbXZXZXbXbXZXbXZXbXbXbXbXbXZXbXbXbXZXZXbXbXbXZXbXbXbXZXZXbXbXZXbXbXbXbXbXbXbXbXbXbXbXbXZXZXbXbXbXZXbXbXbXbXZXbXZXbXbXbXZXZXbXZXbXbXbXbXZXZXbXZXbXbXbXbXbXbXbXsX` X X X X X X X X X X X X X X X X X X X X X X X X X X X ' qXZXbXZXbXbXbXbXSXbXbXbXSXbXSXbXbXbXbXSXbXbXbXbXbXZXZXbXbXbXbXbXbXSXbXbXbXbXbXbXbXbXSXbXbXbXZXZXbXbXZXbXbXZXbXbXZXbXbXbXZXbXbXZXbXbXZXbXbXbXZXbXbXZXZXbXbXbXbXZXbXZXZXbXZXbXvXZXZXZXvXZXbXZXbXbXZXbXbXbXZXbXbXZXbXbXbXZXZXbXZXbXZXZXbXbX", -"ZXbXZXbXbXbXbXbXbXZXZXbXbXZXbXZXbXZXbXbXbXZXbXbXbXZXZXbXZXbXbXbXbXbXbXZXZXbXbXbXZXbXZXbXbXZXZXbXZXbXZXbXbXbXbXbXbXZXZXbXbXbXZXbXbXZXbXbXbXbXbXbXbXSXbXbXbXbXbXbXbXbXbXZXZXbXbXZXZXbXbXZXbXbXZXbXbXbXbXbXbXbXZXbXbXbXbXbXbXbXZXbXbXbXbXbXbXqX^ X X X X X X X X X X X X X X X X X X X X ^ qXZXbXZXbXZXSXZXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXZXbXbXbXbXbXbXSXbXbXbXbXbXbXbXSXbXbXbXbXbXbXbXbXbXbXZXbXZXbXbXZXZXbXbXbXbXbXZXbXZXbXZXZXbXZXbXbXZXbXbXbXZXZXZXbXbXZXbXbXbXbXZXZXbXvXZXZXbXbXZXbXZXZXbXZXbXbXbXZXbXZXZXbXbXbXZXbXZXbXbXbXZX", -"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXZXbXbXZXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXqX^ X X X X X X X X X X X X X ^ qXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXZXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXZXvXZXbXZXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX", -"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXbXbXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXbXbXbX7XN X X X u 7XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXvXZXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXbXbXbXbXbXbXbX", -"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXZXZXvXZXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXvXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX6Xy X X X X X X X X X X . r ,XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXZXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX", -"bXbXbXvXbXvXbXbXbXvXbXbXbXvXvXbXvXvXvXbXbXvXvXbXbXvXvXbXvXbXbXbXbXbXvXbXvXbXvXbXvXbXvXbXvXbXbXvXbXbXbXbXbXvXvXbXbXbXbXbXbXvXvXbXbXbXbXbXbXbXbXvXbXbXvXbXvXbXbXbXbXbXvXbXvXbXbXvXbXbXbXvXbXvXbXbXbXbXbXbXbXbXbXvXbXbXvXbXvXbXbXvXbXbXbXvXbXvXbXbXbXbXvXbXbX,Xw X X X X X X X w ,XbXbXbXbXbXbXvXvXbXvXbXvXbXbXbXbXvXbXbXvXbXvXbXvXbXbXbXvXbXbXbXvXbXbXvXbXbXbXbXbXbXvXbXbXvXvXbXvXbXbXbXbXbXvXbXbXvXbXbXvXbXbXbXbXbXbXbXvXbXvXbXbXbXbXbXbXbXbXbXvXbXvXbXbXvXbXvXvXbXbXbXvXbXbXvXbXbXvXvXvXbXbXvXbXvXvXbXvXbXbXbXbXvXbXbXvXbXvXbXvXbXbXvXvXbX", -"vXvXbXbXvXbXvXbXvXbXvXvXvXbXvXbXvXZXvXvXvXbXvXbXvXbXvXbXbXvXbXvXbXbXbXvXbXvXbXvXbXvXbXvXbXbXvXbXbXvXbXvXvXbXvXbXbXbXvXvXvXbXvXbXbXbXvXbXvXvXbXbXbXbXbXbXvXvXbXvXvXbXvXbXbXvXbXbXvXvXbXbXvXbXvXvXbXbXvXbXvXvXbXbXbXbXvXbXbXvXbXbXbXvXbXbXvXbXvXvXbXbXvXbXvXbXvXK.6 X X X X X X X X X X X X X X X X X X X X X w ;XbXvXbXbXbXbXvXbXbXvXbXbXvXvXbXbXbXvXvXbXvXvXbXvXbXvXbXvXbXbXvXbXvXbXvXvXvXbXvXvXbXvXbXvXbXbXbXbXvXbXvXvXbXbXvXvXbXvXbXvXvXbXvXbXvXbXvXbXvXbXvXvXbXbXvXvXbXbXvXbXvXvXbXvXbXbXbXvXbXbXvXbXvXbXvXvXvXbXvXvXbXvXbXbXbXvXbXbXvXvXbXbXbXvXvXbXvXvXbXvXbXvXbXvXbXbXvX", -"vXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXbXvXvXvXvXbXbXvXvXvXvXvXvXbXbXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXbXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXbXvXvXvXvXvXvXbXbXvXvXvXvXvXvXvXbXK.9 X X X X X X X X X X X X X X X X X X X X X X X 2 K.vXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvX", -"vXvXvXvXvXvXvXvXbXcXbXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXxXJ.: X X X X X X X X X X X X X X X X X X X X X X X X : J.xXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXbXcXcXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvX", -"vXvXvXvXvXbXvXvXbXbXcXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXvXvXvXvXvXvXvXcXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXcXJ.- X X X X X X X X X X : J.cXvXvXbXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXbXbXbXbXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvX", -"vXvXbXvXvXvXcXvXvXvXvXcXcXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXcXvXvXcXvXvXvXvXvXvXvXvXcXbXvXvXvXvXvXvXcXvXvXcXbXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXcXcXvXvXcXcXvXcXvXvXvXvXcXvXvXcXvXbXvXvXcXvXvXvXcXvXcXvXvXvXcXcXvXvXvXvXvXvXcXcXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvXjXi.= X X X X X X X X X & i.jXvXvXvXvXvXvXcXvXcXcXvXvXvXcXvXvXvXvXcXvXvXvXvXcXvXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXcXvXvXvXvXvXvXvXvXvXvXcXvXvXvXvXcXvXcXvXcXcXvXvXvXvXcXcXcXcXcXbXcXbXvXvXcXvXvXvXcXvXvXvXvXvXvXvXcXvXvXvXvXvXvXvXvXvXvXvXvXvXcXvXvXvXcXvXcXvXvXvXvXcX", -"vXcXcXcXvXcXbXcXcXcXvXvXcXvXcXvXcXvXvXcXvXcXvXxXcXvXcXvXvXvXcXvXcXvXcXvXvXcXvXcXvXvXcXvXcXcXcXvXvXcXvXcXvXcXcXvXvXcXvXcXvXvXcXvXvXcXvXcXvXvXvXvXvXvXvXvXcXvXcXvXvXvXcXvXcXvXcXvXvXcXvXcXvXvXvXvXvXcXvXvXcXvXvXvXvXcXvXvXcXvXcXvXcXvXcXvXvXcXvXvXcXvXcXvXvXcXvXcXcXvXvXcXvXcXvXvXjXi.& X X X X X X X X X X X & i.jXcXvXcXvXvXcXvXcXvXvXvXvXcXcXvXvXvXcXvXcXvXcXvXcXvXvXvXcXcXvXvXvXvXcXvXcXcXvXcXvXvXvXcXbXcXvXcXvXvXcXvXcXcXvXcXvXcXvXvXvXcXvXcXvXvXcXvXcXcXvXcXvXvXvXvXcXvXcXvXvXvXvXvXvXcXvXcXvXvXvXbXvXbXcXvXcXcXvXvXvXcXvXvXvXvXcXcXvXcXvXcXvXvXcXvXcXcXvXcXvXvXcXvXcXvXvXcXvXvXvXvXvXcXvXcXvX", -"cXcXvXcXcXvXcXcXcXcXvXcXcXvXcXvXvXcXvXcXvXcXvXvXvXcXcXvXvXcXcXvXvXcXvXcXcXvXxXvXcXvXcXcXcXvXcXvXcXcXvXcXcXvXcXvXcXvXcXvXvXcXvXcXcXvXcXvXvXcXvXcXcXcXvXcXvXcXvXvXcXcXcXcXcXvXcXcXcXvXcXvXvXcXvXcXcXcXvXvXcXvXcXcXcXvXcXvXcXvXcXvXvXcXvXcXvXcXvXcXvXcXvXcXcXcXxXvXvXcXvXcXvXcXvXcXcXvXfX} o X X X X X X X X X X X X X O } fXcXvXcXvXcXcXcXbXcXvXcXvXcXvXvXcXvXcXcXvXcXvXxXvXcXvXcXcXcXcXvXcXcXvXvXcXvXcXcXvXvXcXvXcXvXxXcXvXcXvXcXcXcXvXcXcXvXcXvXcXvXcXvXvXcXvXcXvXcXvXvXcXvXcXcXvXcXvXcXvXcXvXcXvXcXvXcXvXcXvXcXvXcXcXvXvXvXcXvXcXcXcXcXvXcXvXcXvXvXvXcXvXcXvXcXvXcXvXvXcXvXcXcXvXvXcXvXcXvXcXvXcXvXcXvXcXcXvX", -"vXvXcXvXvXcXxXbXbXvXcXvXvXcXvXcXcXvXcXvXcXvXcXcXcXvXvXcXcXvXvXcXcXvXcXvXvXcXvXvXcXcXcXvXvXcXcXcXcXvXcXvXcXcXvXcXvXcXvXcXcXvXcXvXvXcXvXcXcXvXcXvXcXvXvXvXcXvXxXvXcXvXcXvXvXvXvXcXvXcXvXcXcXcXcXvXcXvXvXcXvXcXvXcXvXcXvXcXvXcXvXcXcXvXcXvXcXvXcXvXcXvXcXvXvXcXvXvXcXvXcXvXcXvXcXvXvXcXvXcXfX} O X X X X X X X X X X X X X X X X X X X O } fXcXcXvXvXcXcXbXcXcXcXvXcXvXcXvXcXcXvXcXvXvXcXvXcXvXcXvXcXcXvXvXcXxXvXvXcXcXvXcXvXvXcXcXvXcXvXcXvXvXcXcXcXcXvXvXcXvXcXcXvXcXvXcXvXcXcXvXcXvXvXvXcXcXvXcXvXvXcXvXcXvXxXvXcXvXxXvXcXvXcXcXcXcXvXvXcXvXvXcXvXcXvXvXcXvXcXvXcXcXcXcXvXvXcXvXcXvXvXvXcXcXvXcXcXvXcXcXvXcXvXcXvXcXcXxXvXvXvXvXcX", -"cXvXvXcXcXvXcXcXcXvXcXvXcXvXcXvXcXvXcXvXvXcXcXvXcXvXcXvXvXcXcXvXcXvXvXcXcXvXvXcXcXvXvXcXcXvXcXvXcXcXvXcXcXvXcXvXvXcXcXcXvXcXvXcXvXcXcXcXvXcXvXcXcXcXcXcXvXcXcXvXcXvXvXcXvXxXvXcXvXcXcXcXcXvXcXvXcXcXcXcXvXcXvXcXvXcXcXcXcXcXcXcXcXcXcXvXvXcXcXvXcXvXvXcXcXvXvXvXcXvXcXvXvXcXvXcXvXcXcXcXcXvXqX` X X X X X X X X ` qXcXvXcXvXcXcXvXvXcXvXvXcXvXvXcXcXcXvXcXvXvXcXcXvXcXvXvXcXcXvXvXcXvXvXvXvXcXvXvXcXvXcXcXvXcXvXvXcXcXvXcXvXvXcXvXvXcXvXcXvXcXvXcXvXvXcXvXcXcXvXcXcXcXvXcXvXvXcXcXvXcXvXcXvXcXvXcXvXcXvXvXvXvXcXvXcXvXcXcXcXvXcXvXcXvXvXcXvXcXvXvXcXvXxXcXvXcXvXcXcXcXvXcXvXvXvXcXvXcXvXcXcXcXcXcXbXvXcXcXvXcXvX", -"cXcXcXcXcXvXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXvXcXcXcXvXcXcXvXcXcXcXxXcXvXcXcXcXcXvXcXcXcXvXcXcXcXcXvXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXvXcXcXcXvXvXcXcXcXvXxXcXcXvXcXcXcXcXvXcXcXcXcXcXcXcXcXxXcXcXcXcXvXcXlXlXcXcXcXcXcXcXcXcXcXvXcXcXcXvXvXcXqX` X X X X X X X X X X X X X X X ` qXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXxXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXxXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcX", -"cXvXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcX7X^ X X X X X X X X X X X X ^ 7XvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcX", -"cXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcX7X^ X X X X X X X X X X X X X X H 7XcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXvXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcX", -"cXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXcXcXcXcXlXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcX7Xr X X X X X X X X X X X X X X X X X X X N 6XcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXlXcXcXcXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcX", -"lXcXcXlXlXcXcXlXcXcXlXcXcXcXlXcXcXcXcXlXlXcXcXcXlXcXlXcXcXcXcXlXcXcXcXcXcXcXcXcXcXlXcXcXlXcXlXcXcXcXcXlXcXcXcXcXcXlXcXcXcXlXcXcXcXcXcXcXlXcXcXcXcXlXcXcXcXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXlXcXlXcXlXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXcXlXcXlXvXcXcXcXcXlXcXcXcXcXlXcXcXlXcXlXcXcXcXcXlXlXcXcXcX6Xr X X X X r 6XcXcXcXcXlXcXcXcXcXcXkXcXcXcXcXcXcXcXcXcXkXcXcXcXcXcXcXcXlXcXlXcXcXcXcXcXcXcXlXcXlXcXcXcXlXcXcXcXcXcXcXlXcXcXcXcXlXcXcXcXlXcXcXlXcXcXlXcXcXlXcXcXcXcXcXcXcXlXcXcXcXcXcXcXlXcXlXcXcXcXlXcXcXcXlXcXcXcXcXcXlXcXcXcXcXcXcXkXcXcXcXkXkXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXcXlXcXcXcXcXcXcXcXcXcXcXcXcX", -"cXlXcXlXcXlXcXlXlXcXlXcXcXlXlXcXcXlXlXcXcXlXlXcXlXcXlXcXlXlXcXlXcXlXcXlXlXcXlXcXcXlXcXlXcXlXcXlXlXcXlXcXlXcXlXcXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXlXcXlXlXlXcXkXcXlXcXlXcXcXlXcXlXcXlXcXcXlXcXkXcXcXcXkXcXlXcXcXlXcXlXcXcXlXcXcXlXcXlXcXlXcXlXkXcXcXlXlXcXlXcXcXlXcXlXlXcXlXcXcXlXcXlXlXcXlXcXlXcX6Xw X X X X X X X X X X w 6XlXcXcXlXlXcXcXcXkXcXkXcXcXcXcXkXcXkXkXcXkXcXcXkXcXlXlXcXcXlXcXlXlXcXlXcXcXlXcXlXcXlXcXlXcXlXcXlXcXlXlXcXlXcXlXlXcXlXcXcXkXlXlXcXlXcXlXlXcXlXcXlXcXkXcXlXlXcXlXcXcXlXlXcXcXlXcXlXlXcXlXcXlXcXlXcXlXcXcXlXcXlXcXlXcXlXcXcXkXcXcXcXcXcXcXkXcXcXcXcXkXkXcXkXcXlXlXcXlXcXlXcXlXcXlXcXlXlXcXcXlXcXcXlXcXlXcXlXcXlXlXlXcXlX", -"lXcXlXcXlXcXlXcXcXlXcXlXlXcXlXlXlXlXcXlXlXcXcXlXcXlXcXlXcXcXlXlXlXcXlXcXcXlXcXlXlXcXlXcXlXcXlXcXcXlXcXlXcXlXcXlXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXcXlXlXcXlXlXcXcXlXcXcXcXlXcXcXkXcXlXcXlXcXlXlXcXlXcXcXkXcXcXlXcXlXlXcXlXcXcXlXcXlXlXcXlXcXlXcXlXcXcXcXkXcXcXlXcXlXlXcXlXcXcXlXcXlXlXcXlXcXcXlXcXlXcXlXjXlXK.6 X X X X X X w K.lXcXlXlXlXcXlXlXkXcXlXcXcXcXkXcXcXcXcXcXcXcXkXcXcXcXcXcXcXlXlXcXlXcXcXlXcXlXlXcXlXcXlXcXlXcXlXcXlXcXlXcXcXlXcXlXlXcXlXcXkXcXcXcXcXlXcXlXlXcXlXcXlXcXlXcXlXcXcXlXcXlXlXcXcXlXlXcXlXcXcXlXcXlXcXlXcXlXcXlXlXcXlXcXlXcXlXcXkXcXcXcXkXcXkXcXcXcXcXkXcXkXcXcXcXcXcXkXcXlXcXlXcXkXcXcXlXlXcXlXlXlXcXlXlXcXlXcXlXcXlXcXcXlXlXcX", -"cXlXlXlXlXlXlXcXlXcXcXlXcXlXlXcXcXlXcXlXlXcXlXlXlXcXlXcXlXcXcXcXlXlXcXlXlXcXlXlXcXlXlXcXcXlXlXlXlXlXlXcXlXcXlXlXcXlXlXlXlXlXcXlXcXlXcXlXlXlXlXlXcXlXlXlXlXlXcXlXcXlXcXlXlXcXlXlXcXkXcXcXkXcXcXlXlXcXcXlXlXcXlXlXcXlXcXkXcXkXlXcXlXcXcXlXlXcXlXlXcXlXlXlXlXlXlXlXcXkXcXlXlXcXlXlXcXlXlXcXlXlXlXcXlXcXcXlXlXcXlXlXlXcXlXcXcXcXK.2 X X X X X X X X X X X X X X X X 9 K.cXlXcXlXlXcXlXcXcXcXlXcXcXkXkXcXkXcXkXcXkXcXkXcXcXcXcXkXcXcXlXlXcXlXlXcXlXcXlXcXlXlXcXlXlXcXcXlXlXcXcXlXlXcXlXlXlXcXcXlXcXlXcXlXlXcXlXlXlXcXcXlXcXlXcXlXlXcXlXcXlXcXlXlXcXlXlXlXlXcXlXcXlXcXlXcXlXlXlXcXcXlXcXlXcXlXlXlXlXlXcXcXcXkXcXkXcXkXcXkXcXkXcXcXcXkXkXcXlXcXlXlXcXcXcXcXcXkXcXcXlXcXlXcXlXlXcXlXlXlXlXlXlXlXcXlXlXcX", -"lXlXcXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXjXcXlXlXlXlXlXlXlXlXlXlXlXlXcXlXlXlXlXlXlXlXlXlXlXcXlXlXlXlXcXlXlXlXlXlXlXlXlXlXlXlXlXcXkXkXkXcXkXkXcXlXlXlXlXlXlXlXlXkXcXkXcXkXcXlXlXlXlXlXlXlXlXlXlXlXlXlXcXlXlXlXlXkXcXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXG.1 X X X X X X X X X X X X X 1 G.jXlXlXlXlXlXlXlXlXkXkXcXkXlXkXcXcXkXcXkXcXkXcXkXcXcXkXkXkXcXkXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXcXlXlXkXcXkXcXkXcXkXcXkXcXkXcXkXcXkXcXlXlXkXcXlXlXkXlXkXkXkXcXkXlXlXlXlXlXlXlXlXlXlXcXlXlXlXlXlXlXlXlX", -"lXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXcXkXcXcXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXcXkXcXlXlXlXkXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXcXkXcXlXlXlXlXlXkXlXlXlXlXlXlXkXcXkXcXkXcXcXkXcXkXkXcXlXlXlXlXlXjXG.- X X X X X X X X 1 i.jXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXkXkXcXcXkXkXkXcXlXlXkXkXlXlXlXlXlXlXkXkXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXcXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXkXlXlXlXlXlXlXlXlXkXcXkXcXkXcXcXkXlXlXlXlXkXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlXlX", -"lXkXkXlXkXlXlXkXkXlXkXlXkXlXlXkXlXlXlXkXkXkXkXkXkXlXlXkXlXkXkXlXlXlXlXkXkXlXlXkXlXkXlXkXkXlXlXkXlXkXkXlXkXlXkXlXlXkXlXkXlXlXlXkXjXlXlXkXkXlXkXlXlXkXlXkXkXlXkXlXkXlXkXkXlXkXcXkXkXlXlXkXcXkXkXlXkXlXlXkXlXkXkXlXlXkXlXlXkXkXkXlXkXkXlXkXkXlXkXlXlXkXkXlXkXlXkXlXlXkXkXkXlXkXkXlXkXlXkXlXlXkXlXkXcXkXkXkXkXlXkXkXlXkXkXkXlXkXkXlXlXlXlXgXr.O X X X X X X X X X $ r.gXkXkXlXlXlXkXlXkXlXlXkXlXkXkXlXlXkXlXlXkXlXkXlXlXkXlXkXkXlXkXkXkXcXkXcXlXkXlXkXkXlXkXlXlXkXlXkXkXlXkXlXjXkXlXkXlXlXlXkXkXlXkXlXkXlXkXkXlXkXkXlXlXkXkXlXlXkXkXlXkXkXkXkXkXlXkXlXkXlXkXkXlXkXlXkXkXlXkXkXkXlXkXlXlXkXlXkXlXkXkXlXlXkXlXlXkXlXkXlXkXlXlXkXkXcXkXkXkXkXkXkXlXkXlXkXlXlXkXlXlXkXlXkXkXlXkXlXlXlXlXlXkXlXlXkXlXkXlXkXkXlXlXkX", -"lXlXlXkXlXkXlXkXlXlXlXlXkXlXkXlXlXkXkXkXkXkXlXcXlXkXkXlXlXlXkXkXkXlXkXlXlXkXkXkXlXlXlXlXlXkXkXlXkXkXkXkXlXlXlXlXkXlXlXkXkXkXkXkXlXkXkXlXlXlXkXkXkXlXkXlXlXlXlXlXlXkXkXkXkXkXcXkXlXkXkXkXkXkXkXkXlXkXkXlXlXlXlXlXkXlXkXkXlXlXlXlXkXlXkXkXlXkXlXkXkXlXkXlXlXkXlXkXlXlXkXlXlXlXkXlXlXlXlXlXkXlXlXkXkXkXlXlXlXkXkXcXkXkXkXcXlXlXkXlXkXlXlXlXlXgXr.# X X X X X X X X X X X X X $ r.gXkXlXlXlXkXlXkXlXkXkXlXkXlXlXlXlXlXkXlXkXkXlXlXlXlXkXlXlXkXkXcXkXlXkXcXkXkXkXlXlXlXlXkXlXkXkXlXlXlXlXkXkXlXlXlXlXkXlXkXkXkXlXlXlXlXkXkXkXkXkXlXkXkXkXlXkXkXlXkXlXkXkXlXkXkXkXlXkXlXlXkXkXkXkXlXlXlXlXkXkXkXlXkXlXlXkXlXlXkXlXlXkXlXkXkXlXlXlXlXlXlXkXlXkXlXkXkXkXkXkXkXkXcXkXlXlXlXkXlXkXlXkXlXlXlXlXkXkXlXkXlXlXkXlXkXkXkXlXlXlXlXkXlXkXlX", -"kXkXlXkXlXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXkXlXkXkXkXlXkXkXkXkXkXkXkXkXlXkXlXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXlXkXkXkXkXkXkXkXlXkXlXkXkXkXkXkXkXkXkXlXkXkXkXkXlXkXlXkXkXkXkXkXlXkXkXkXkXkXkXkXlXkXlXkXkXkXkXlXkXlXkXkXlXkXlXlXkXlXkXkXlXkXkXkXlXlXkXkXlXkXlXkXkXkXkXlXkXlXkXkXkXkXkXkXkXkXkXkXkXkXlXkXlXkXlXlXkXlXlXlXlXlXyX} O X X X X X X . } yXcXlXkXlXkXkXkXkXlXkXlXlXkXlXkXkXkXkXkXkXlXkXlXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXlXkXlXkXkXkXkXkXlXkXlXkXkXkXlXkXkXkXkXkXkXkXkXkXlXlXkXlXlXkXkXkXlXkXlXkXkXlXkXlXlXkXkXkXlXkXlXkXkXlXkXkXkXkXkXkXlXkXkXkXkXlXkXkXlXkXlXkXkXkXlXkXkXlXkXkXkXkXkXkXkXlXkXkXkXcXkXkXkXcXkXkXkXkXkXlXkXkXlXkXkXkXkXkXlXkXlXkXkXkXlXkXlXkXkXkXkXkXkXkXkXlXkXkX", -"kXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXlXlXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXyX} X X X X X X X X X X X } yXkXcXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXkXkXkXlXkXkXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXlXlXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkX", -"kXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXkXkXkXhXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXyX` X X X X X X X X X X X X X X . ` 8XkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXhXkXkXkXhXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXlXhXhXkXkXlXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkX", -"kXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXqX` X X X X X X X X ` qXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXlXkXkXlXlXkXkXkXhXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXhXkXhXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkX", -"hXkXkXhXkXhXkXkXkXkXkXkXhXkXkXhXkXhXkXkXkXhXhXkXkXkXkXkXkXkXhXkXkXkXkXhXkXhXkXkXhXkXhXkXkXhXkXkXkXhXkXkXhXkXhXkXkXkXkXkXkXkXkXhXkXkXkXkXkXkXhXkXkXkXkXkXhXkXkXkXkXkXhXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXhXkXhXkXkXhXkXhXkXkXhXkXkXhXkXhXkXkXkXhXhXkXkXhXkXkXkXkXhXkXhXkXkXkXhXkXkXhXkXhXkXkXkXhXkXkXkXkXhXkXkXhXkXkXkXkXkXkXhXkXkXhXhXkXkXkXkXkXhXkXkXhXhXkXhXkXkX7XH X X X X X X X X X H 7XhXkXkXkXkXhXkXkXhXkXkXkXhXkXhXkXkXkXkXhXkXkXhXkXkXhXkXkXhXkXkXkXhXkXhXkXkXhXkXkXkXhXkXkXkXkXkXkXkXkXkXhXkXkXhXkXkXkXkXhXkXkXkXkXkXkXhXkXhXkXkXhXlXhXlXhXhXlXhXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXkXkXkXkXhXkXkXkXkXkXkXkXhXkXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXkXhXkXkXhXkXhXkXkXkXhXkXkXkXkXkXkXkXkXhXkXkXhXhXkXkXkXhXkXkXhXkXkXhXkXkXkXkXkXhXkXhXkXkXhXkXkXhXkXkXkX", -"kXkXkXkXhXkXkXhXhXkXkXhXkXhXkXkXhXkXkXkXkXhXkXkXkXkXhXkXkXhXkXkXkXkXkXkXhXkXkXhXkXkXkXkXhXkXkXhXhXkXkXkXkXhXkXkXhXkXkXkXkXkXkXkXkXkXkXkXhXkXkXhXhXkXkXhXkXhXkXkXkXkXhXkXkXhXkXhXhXkXhXkXkXkXkXkXkXkXhXkXkXhXkXhXhXkXkXhXkXkXkXkXhXkXkXkXkXhXkXkXkXkXhXkXkXkXkXkXkXkXkXkXhXkXkXhXhXkXkXhXkXkXhXkXkXhXkXhXkXkXhXkXkXhXkXkXhXkXhXkXhXkXkXhXkXkXhXkXkXhXkXkXhXkXhXkXkX7XH X X X X X X X X X X H 7XkXhXhXkXkXhXkXhXkXkXkXkXkXkXhXkXkXhXkXhXkXhXkXkXhXkXhXkXkXkXkXhXkXhXkXkXhXkXhXkXkXhXkXhXkXkXhXkXhXhXkXhXkXkXkXkXhXkXkXhXkXhXkXkXhXhXkXkXkXkXkXkXkXkXhXlXhXkXlXhXlXkXkXhXkXhXkXkXhXhXkXkXhXkXkXhXkXkXhXkXkXhXkXhXkXkXkXhXkXhXkXkXhXhXkXhXkXhXkXkXkXkXhXkXkXkXkXhXkXhXkXkXhXkXhXkXhXkXkXhXkXhXkXkXkXkXkXhXkXkXkXkXhXkXhXkXhXkXkXhXkXkXhXkXkXhXkXhXkXhXkXkXhXkXkXkXkX", -"hXhXhXhXkXkXhXkXkXhXkXhXhXkXkXhXkXhXhXhXhXkXhXkXhXhXkXhXhXkXhXhXhXhXhXhXkXkXhXkXhXhXhXkXkXhXkXhXkXhXhXhXhXkXhXkXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXkXkXhXkXhXhXkXhXhXhXkXkXhXhXkXhXkXkXhXkXkXhXhXhXhXhXhXkXhXhXkXhXkXkXhXkXhXhXhXhXhXkXhXhXhXhXkXhXkXhXkXhXkXhXhXhXhXhXhXhXhXkXkXhXkXkXhXhXkXhXkXkXhXkXhXhXkXkXhXkXhXhXkXhXhXkXhXkXkXkXkXhXkXhXhXkXhXhXkXhXkXkXhXkXhXhXhXhX[.n X X X X n 6XhXhXhXhXkXhXkXkXhXkXhXhXkXhXhXhXkXkXhXhXkXkXhXkXhXhXkXhXkXhXhXhXhXkXhXkXhXhXkXhXkXhXkXkXhXkXhXkXhXhXkXhXhXkXhXhXhXhXkXhXkXkXhXkXhXhXkXhXkXhXhXhXhXhXhXhXkXhXkXhXhXhXhXhXkXkXhXkXhXkXhXkXkXhXkXhXhXkXhXhXkXhXkXkXhXkXhXhXkXkXhXkXhXhXkXhXkXkXhXkXhXhXhXhXkXhXhXhXkXkXhXkXhXhXkXkXhXhXkXhXkXkXhXkXhXhXhXhXkXkXhXhXhXhXkXkXhXhXkXhXhXkXhXhXkXhXhXkXkXhXkXkXhXkXhXhXhXhXhX", -"kXhXhXkXhXkXkXhXhXhXkXkXhXkXhXhXhXkXkXhXkXkXhXhXhXkXkXkXkXhXkXhXkXhXhXkXhXkXkXhXkXkXhXhXkXhXhXkXhXkXkXhXkXkXhXhXkXhXkXhXhXkXhXkXkXhXhXkXkXhXkXhXhXhXkXkXhXkXkXhXkXhXkXkXhXkXhXhXhXkXkXhXkXhXhXkXhXkXhXkXkXhXkXhXhXhXkXkXhXkXkXhXhXkXkXhXkXkXhXhXhXhXhXhXkXhXhXkXkXhXhXkXhXkXkXhXhXhXkXkXhXkXhXhXkXhXhXkXhXhXkXkXkXhXhXkXhXkXkXhXhXhXkXhXhXkXhXkXkXkXhXhXkXhXhXkXkXkXkXhXkX6Xr X X X X X X X X X X X r 6XhXhXhXkXkXkXkXhXhXkXhXhXkXhXhXkXhXhXkXhXhXkXhXhXkXhXkXkXhXhXkXkXhXkXkXkXkXkXhXkXhXkXhXhXkXkXhXhXkXhXkXkXhXkXkXkXkXhXkXkXhXkXhXhXkXhXhXkXkXkXhXkXhXhXkXhXkXhXhXhXhXhXlXhXlXkXhXhXkXhXhXkXkXhXhXkXhXhXkXhXkXkXkXhXhXkXhXhXkXkXhXhXkXhXhXkXkXhXkXhXkXhXkXkXhXhXkXkXhXkXhXhXkXkXhXhXkXkXhXhXkXkXhXhXkXhXkXkXhXkXkXhXkXhXkXkXhXhXkXkXhXkXkXhXkXkXhXhXkXhXkXkXhXhXhXkXkXhXkXkXhX", -"kXhXkXhXhXhXhXkXhXkXhXhXkXhXhXkXkXhXhXkXhXhXhXkXhXhXhXhXkXhXhXkXkXhXkXhXhXhXhXkXhXhXkXhXhXkXhXhXkXhXhXkXhXhXkXhXhXkXhXkXhXhXkXhXkXhXkXhXhXkXhXkXhXkXhXhXhXhXhXkXhXhXhXhXkXhXhXkXhXhXhXhXkXhXkXhXhXhXkXhXhXkXhXkXhXkXhXhXhXhXkXhXkXhXhXkXhXhXhXkXhXkXkXhXkXhXhXkXkXhXkXhXhXhXhXkXhXkXhXhXkXhXhXkXhXkXhXhXhXkXhXhXkXhXhXkXhXhXhXkXhXkXhXkXhXhXkXhXhXhXhXkXhXkXhXhXhXhXhXkXkXkXaX[.w X X X X X w [.kXkXhXhXkXhXhXhXhXhXkXhXkXhXhXkXhXhXkXkXhXhXkXhXkXhXhXkXhXhXkXkXhXhXkXhXhXhXhXhXhXkXhXhXkXhXhXhXkXhXhXkXhXhXkXhXhXhXhXhXhXkXhXhXhXkXhXkXhXhXhXhXkXhXkXhXhXkXhXlXhXlXhXhXhXhXhXhXhXkXhXhXkXhXhXhXkXhXkXhXhXkXhXhXhXhXkXhXkXhXhXhXhXkXhXkXhXhXhXkXhXhXhXkXhXhXkXhXhXkXhXhXhXkXhXhXkXhXhXhXkXhXhXhXkXhXhXkXhXhXkXhXhXkXhXhXhXkXhXkXhXhXkXhXhXkXhXkXhXkXhXhXhXhXkXhXkXhXhXhXhXkXhX", -"hXhXhXhXkXhXhXhXhXkXhXhXhXhXhXhXkXhXhXhXkXhXhXhXhXkXhXhXhXkXhXhXhXhXhXhXkXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXkXhXhXhXhXkXhXhXhXhXhXkXhXkXhXhXhXhXkXhXhXkXhXhXkXhXhXhXhXhXhXkXhXkXhXhXkXhXhXhXkXhXhXhXhXhXhXkXkXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXhXhXhXhXhXhXkXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXkXhXhXkXhXhXkXhXhXkXhXhXhXhXK.w X X X X X X X X X w K.hXkXkXhXhXhXhXhXkXhXhXkXhXhXhXhXkXkXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXkXhXhXkXhXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXhXkXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXkXhXhXhXhXkXhXhXkXhXhXhXhXkXhXhXhXkXhXhXhXhXhXhXkXhXhXhXhXkXhXhXkXhXhXhXhXhXhXkXhXkXhXhXkXhXhXhXhXhXhXkXhXkXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXkXhXhX", -"hXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXK.3 . X X X X X X X 6 K.hXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhX", -"hXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXgXi.- . X X X X X 1 G.gXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhX", -"hXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXi.1 X X X X X X X X X : G.aXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXkXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXkXhXhXhXhXhXhXhXhXhXhXkXhXhX", -"hXhXhXaXhXaXhXhXhXhXhXhXhXaXhXhXaXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXhXaXhXhXaXhXhXuXr.& X X X X = r.uXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhX", -"hXhXhXhXhXhXaXhXaXhXaXhXhXhXhXhXhXhXhXhXaXhXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXaXaXhXhXhXaXhXhXaXhXaXaXhXhXhXhXhXhXhXaXhXhXaXhXaXaXhXhXaXaXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhXhXhXaXhXhXaXhXhXhXhXaXhXhXaXaXhXhXaXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhXhXaXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXyXr.& X X X X X X X X # r.uXhXhXhXhXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhXhXhXaXhXhXaXhXaXhXhXaXhXhXhXaXhXaXhXaXhXaXhXaXhXaXhXaXhXaXhXaXhXhXaXhXaXhXaXhXaXhXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhXaXhXhXaXaXhXhXhXhXhXhXhXhXaXaXhXaXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhXhXhXaXhXhXaXhXaXaXhXhXaXaXhXhXaXhXaXhXhXhXaXhXhXaXhXaXhXaXhXaXhXhXaXhXhXhXaXhXhXaXhXaXhXaXhXaXhXhXhXhXaXaXhXhXaXhXhXaXhXhXaXhXaXaXhXhXaXaXhXhXaXaXhXaXhXhXaXaXhX", -"aXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXhXhXhXhXhXhXhXhXaXhXaXhXhXhXhXhXhXaXhXhXhXhXaXhXaXaXhXaXhXhXhXaXhXhXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXaXhXhXhXhXhXhXhXaXhXhXhXhXhXhXaXaXhXaXhXhXaXhXhXaXhXhXaXhXhXaXhXhXhXhXaXhXaXhXhXhXhXhXhXaXhXhXhXhXhXhXaXaXhXaXhXhXaXhXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXhXhXhXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXhXaXaXhXaXhXhXhXaXhXhXhXaXhXhXaXaXhXaXhXhXaXhXhXaXhXyX[ O X X X X X o [ yXaXhXhXaXhXaXhXhXhXhXhXhXhXaXhXaXhXhXhXaXhXhXaXhXhXhXhXhXhXaXhXhXaXhXhXhXaXhXhXaXaXhXhXaXhXhXaXhXhXhXaXhXhXhXhXhXhXhXaXhXaXhXhXhXhXaXhXhXaXhXhXhXhXhXhXaXhXhXaXhXhXhXhXhXaXhXhXaXhXhXaXhXhXhXaXhXhXhXhXhXaXhXhXaXhXhXhXaXhXhXaXhXhXhXhXhXhXaXhXhXaXhXhXhXhXaXhXaXhXhXhXhXaXhXhXaXaXhXhXaXhXhXhXhXhXhXhXhXaXhXhXaXaXhXhXaXhXhXhXhXhXhXhXhXhXhXhXhXhXaXhXaXhXaXhXhXaXhXhXhXhXaXhXaXhXhXhXhXhXhXaXhXhXhXhXhX", -"aXhXaXaXaXhXaXaXaXhXaXaXaXaXaXaXaXaXhXaXaXhXaXaXaXaXaXhXaXhXaXhXaXhXaXaXaXhXhXpXpXhXpXhXhXaXhXhXhXpXhXpXhXhXhXpXhXaXaXhXhXaXaXhXaXhXaXaXaXaXhXaXaXhXaXaXaXhXhXaXaXhXaXaXhXaXhXhXhXaXaXhXaXaXhXaXhXaXaXhXhXaXaXhXaXhXaXhXaXhXaXaXaXhXhXaXaXaXhXaXhXaXhXhXhXaXaXhXaXhXaXhXhXhXaXaXhXaXaXhXaXaXaXhXhXhXaXhXaXhXaXhXaXhXhXaXaXaXhXaXaXhXaXaXaXaXaXhXhXhXaXhXhXaXhXhXaXhXhXaXaXaXhXaXhXaXhXhXhXaXaXhXaXhXhXaXhXaXyX[ o X X X X X X } yXaXaXhXhXaXhXhXaXaXhXaXaXaXhXhXhXaXhXaXhXaXhXaXhXhXaXaXaXhXaXhXaXaXhXhXaXaXhXhXaXhXaXhXaXhXaXhXaXhXaXhXaXhXhXaXaXaXaXhXaXhXhXaXhXaXhXaXhXaXhXhXhXaXaXaXhXaXhXaXhXhXaXaXaXhXaXhXaXhXhXaXhXhXaXaXaXhXaXhXaXaXhXhXhXaXhXaXhXaXhXaXhXhXaXaXaXhXaXhXaXaXhXhXaXaXhXaXhXaXhXaXhXaXaXhXaXhXaXhXaXhXaXaXaXaXhXaXaXaXhXhXaXhXaXhXaXhXaXaXaXaXhXaXaXaXhXaXaXaXhXaXhXaXhXhXaXaXhXhXaXaXhXaXhXaXhXaXhXaXaXaXhXhXaXaXaXhXaX", -"hXaXhXaXaXaXhXaXhXaXhXaXaXaXaXaXaXhXaXaXhXaXaXhXaXhXaXaXhXaXhXaXhXaXaXhXaXhXaXhXhXhXaXaXhXaXhXaXaXaXhXaXpXhXpXhXaXaXhXaXaXhXaXaXhXaXaXaXaXhXaXaXaXaXaXhXaXaXaXaXaXaXhXaXaXhXaXaXhXaXaXaXaXaXaXhXaXaXhXaXaXhXaXaXhXaXaXhXaXaXaXhXaXaXaXaXaXhXaXaXaXaXhXaXaXhXaXaXaXhXaXaXaXaXhXaXaXhXaXaXhXaXhXaXaXaXaXhXaXaXhXaXaXaXhXaXaXhXaXaXhXaXaXhXaXaXaXaXaXaXaXhXaXaXhXaXhXaXaXaXaXhXaXaXaXaXhXaXaXhXaXaXaXhXaXaXaXaXhXaX8XE X X X X X X X X X X X X X E 8XaXhXaXaXaXaXhXaXaXhXaXaXaXhXaXaXaXaXaXhXaXaXhXaXaXaXhXaXaXhXaXaXaXaXhXaXaXhXaXaXaXaXhXaXaXhXaXhXaXaXhXaXaXaXhXaXhXaXhXaXaXaXhXaXaXhXaXaXaXaXaXhXaXaXaXhXaXaXhXaXaXaXhXaXaXhXaXaXaXaXaXhXaXaXaXaXaXhXaXaXaXhXaXaXaXaXaXhXaXaXhXaXaXaXhXaXaXhXaXaXaXaXhXaXaXhXaXaXhXaXaXhXaXaXaXhXaXhXaXaXaXaXaXhXaXaXaXhXaXaXhXaXaXhXaXaXaXaXaXhXhXaXaXhXaXaXaXaXaXhXaXaXhXaXhXaXaXaXhXaXaXaXaXaXhXaXaXhXaXaXaXhXaXaXhXaXaXhXaXaX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXaXaXaXpXpXhXaXhXpXaXaXaXhXpXaXpXhXhXpXaXaXaXaXaXaXaXhXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX8X` X X X X X X X ` 8XaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXhXpXaXaXhXpXaXaXpXaXaXaXaXaXaXaXaXaXpXhXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX7XG X X X X H {.aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXhXpXhXaXaXaXaXaXaXaXaXaXaXaXaXaXpXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpX{.H X X H 7XaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaX", -"aXaXaXaXaXpXaXaXpXaXaXpXaXaXpXaXaXpXaXpXaXpXaXaXaXaXaXpXaXpXaXpXpXaXpXaXpXaXpXaXpXhXpXpXaXpXaXpXpXaXpXaXaXpXaXpXaXpXaXpXpXaXpXaXaXpXaXaXaXpXaXpXaXaXpXaXaXpXaXaXaXpXaXpXaXpXaXpXaXaXpXaXpXaXaXpXaXpXaXpXaXaXaXpXaXpXaXpXpXaXaXpXaXaXpXaXaXaXpXaXaXaXaXpXaXaXpXaXaXpXaXaXaXpXaXaXpXaXaXpXaXaXaXaXaXaXpXaXaXaXaXaXaXaXaXpXaXaXpXaXaXpXaXaXpXaXaXpXpXaXaXpXaXaXaXaXaXpXaXpXaXpXaXpXaXpXaXpXpXaXpXaXaXaXaXpXaXpXaXaXpXaXaXpXaXpXaXaX[.n X X X X X n [.aXaXaXaXaXaXaXaXaXaXaXaXpXaXaXpXaXpXaXpXaXpXaXaXaXaXaXaXaXpXaXpXaXaXpXaXaXaXpXaXaXaXaXaXaXaXpXaXaXpXaXaXpXaXaXpXaXpXaXpXaXaXaXpXpXaXaXpXaXaXpXaXpXaXpXaXpXaXpXaXaXpXaXaXaXaXaXaXaXpXaXpXaXpXaXpXaXaXpXaXaXpXaXaXpXaXaXaXpXaXaXaXaXaXpXaXaXaXpXaXaXaXaXpXaXaXpXaXpXaXpXaXpXaXaXaXpXaXpXaXpXaXpXaXaXpXaXaXaXaXaXpXaXpXaXpXaXpXaXpXaXaXaXaXaXaXaXpXaXpXaXaXpXaXpXaXaXaXaXpXaXaXpXaXaXaXaXpXaXpXaXaXaXpXaXpXaXaXaXaXaXaXaXpXaXpXaXpX", -"pXpXpXpXaXpXpXaXaXpXaXpXpXaXaXpXpXaXpXaXpXaXpXpXaXaXpXaXpXaXpXaXaXpXaXpXpXaXaXaXpXpXaXhXpXaXpXpXaXpXaXpXaXpXpXaXpXaXpXaXaXpXaXpXaXaXpXpXaXpXpXaXpXaXaXpXaXpXpXaXpXaXpXaXaXaXpXaXpXaXaXaXaXpXpXaXaXpXpXaXaXpXpXaXpXaXpXaXaXaXpXaXpXaXaXpXpXaXaXpXpXpXpXaXpXpXpXaXpXaXpXpXaXpXpXaXaXpXaXpXpXaXpXpXpXpXaXaXpXpXpXaXpXpXaXpXpXaXaXpXaXpXpXaXaXpXaXaXaXaXpXaXpXpXpXpXpXaXpXaXpXaXpXaXpXaXaXaXaXpXaXpXpXpXpXaXpXpXpXaXaXpXaXpXpXpXpXaXhXaX[.r X X X X X X X X X r [.aXpXpXpXpXaXpXpXpXpXaXaXpXaXaXpXaXpXpXaXpXaXaXaXpXaXpXpXpXaXaXaXpXpXpXaXaXpXpXaXaXpXpXpXpXpXpXpXpXaXaXpXpXaXaXpXpXaXpXaXpXaXaXpXaXpXpXpXaXpXpXaXaXpXaXaXaXpXaXpXaXaXpXaXpXaXpXpXpXpXpXaXaXpXpXaXpXaXpXaXaXpXpXaXpXaXpXaXpXpXpXaXpXpXpXpXaXaXpXpXaXaXaXaXaXpXpXaXaXpXaXaXaXpXaXpXpXaXaXpXaXaXaXpXaXaXaXpXpXaXpXpXpXaXpXaXpXaXpXaXaXpXaXpXpXaXpXpXpXaXaXpXpXaXaXpXaXaXaXaXaXpXpXaXaXpXpXpXpXaXaXpXpXpXpXaXpXaXpXpXpXaXaXaXpXaXpXaXpXaX", -"pXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXaXpXaXaXpXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXaXaXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpX[.w X w [.pXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXaXpXaXpXpXpXpXpXpXpXpXaXpXpXaXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXaXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXaXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXaXpXpXpXpXpXpXpXpXpXaXpXpXpX", -"pXpXpXaXpXpXpXpXpXaXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXaXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXK.6 X X X X w K.pXpXpXpXpXpXpXaXpXpXpXaXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXaXpXpXpXaXpXpXpXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXaXpXpXaXpXpXaXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpX", -"pXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXaXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXK.6 X X X X X 1 K.iXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpX", -"pXpXpXpXpXpXpXpXpXpXpXpXpXiXiXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXiXpXpXpXpXiXpXpXpXpXpXpXiXpXpXpXpXpXpXiXpXpXiXpXpXpXpXpXpXpXpXiXiXpXpXpXpXiXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXiXpXiXpXpXpXpXpXpXpXpXiXpXpXiXpXpXpXpXpXpXpXiXpXpXiXpXpXpXiXpXpXpXiXpXiXpXpXpXpXpXpXiXpXpXiXpXpXpXiXpXpXpXpXpXiXpXpXpXpXpXpXpXpXiXpXiXpXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXiXpXpXpXpXiXpXpXpXpXpXiXiXG.1 X X X X X 1 G.iXpXpXpXpXiXpXpXpXpXpXiXpXpXiXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXiXiXpXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXiXpXiXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXiXpXpXpXpXpXpXiXpXpXpXpXpXiXpXpXpXpXpXpXiXpXpXiXpXpXpXiXpXpXpXpXpXpXpXpXiXpXpXiXpXpXpXpXpXpXpXpXpXiXpXpXpXpXpXiXpXpXpXpXpXpXpXiXpXpXpXiXpXpXpXpXpXiXpXiXpXpXpXpXpXiXpXpXpXpXpXpXpXpXiXpXpXpXpXpXpXpXpXpXpX", -"pXpXiXiXiXpXpXpXiXiXpXpXpXpXpXpXpXiXpXpXpXpXiXpXiXpXpXiXpXiXpXpXpXpXiXpXpXpXpXpXpXiXpXiXpXpXpXiXpXpXiXpXpXpXpXpXpXiXpXiXiXpXiXpXpXpXpXpXpXpXiXiXiXpXpXpXpXpXiXiXpXiXpXpXpXiXpXiXpXiXiXpXpXpXpXpXpXiXpXiXpXpXiXpXpXpXpXiXpXiXpXiXpXiXpXpXpXpXpXpXpXpXiXiXiXpXpXpXpXpXiXpXiXpXiXiXiXpXiXpXpXpXpXpXpXiXpXpXiXpXiXpXpXpXpXiXpXpXpXiXiXpXpXpXiXpXpXpXiXpXiXpXpXpXiXpXpXiXpXpXpXpXiXpXpXpXiXiXiXpXpXpXpXiXpXiXpXpXpXpXpXpXpXpXpXpXpXpXpXiXpXpXpXiXpXiXiXpXiXuXG.- X X : G.iXpXpXpXiXpXiXpXiXpXiXiXpXpXpXiXpXpXiXpXiXpXpXiXpXiXpXpXpXiXpXiXpXpXiXpXpXpXpXiXpXiXpXiXpXiXpXpXpXpXpXpXpXpXiXiXiXiXpXpXiXpXpXpXpXiXpXpXiXpXpXpXpXiXiXpXiXpXpXiXpXiXpXpXpXiXpXpXpXiXiXpXpXpXpXiXpXpXiXpXiXpXpXiXpXiXpXiXpXiXpXiXpXpXpXiXpXpXpXiXpXiXpXpXpXiXpXpXpXiXpXiXpXpXiXpXpXpXpXiXiXpXpXpXpXiXpXpXiXpXpXpXiXpXpXpXiXpXpXpXiXpXpXpXpXiXpXiXpXpXiXpXiXpXpXpXiXpXpXpXiXpXiXpXiXpXpXpXiXiXpXpXpXpXpXpXiXiXpXpXpXpXpXpXpXpXpXiXpXpXpXiXiXpXpXiXpXpXpXiX", -"iXpXpXpXpXiXpXiXpXpXpXiXpXiXiXpXpXpXpXiXiXpXpXpXiXpXpXiXpXpXpXiXiXpXpXpXpXiXiXpXpXpXpXpXiXpXpXpXpXpXpXpXiXpXiXpXpXpXpXpXpXpXpXpXpXiXiXpXiXpXpXpXpXiXpXiXiXpXpXpXpXpXpXiXpXiXpXpXpXpXpXpXiXpXiXpXpXiXpXpXpXiXpXpXiXiXpXpXpXiXpXpXpXpXpXiXiXpXiXpXpXpXpXpXpXiXiXpXpXpXpXpXpXpXpXpXpXpXpXpXiXpXiXpXpXpXpXiXpXpXpXpXpXiXpXpXiXiXpXpXpXpXiXpXiXpXiXpXpXpXiXpXiXpXpXpXpXpXpXiXiXpXpXpXpXpXpXpXpXiXiXpXpXpXpXpXpXiXiXpXpXiXpXiXpXiXiXpXpXpXpXiXpXiXpXpXpXiXpXiXiXeXr.& X X X - e.uXpXpXiXpXiXpXpXpXpXpXpXpXpXiXiXpXpXiXpXpXpXiXpXpXiXpXpXpXiXpXiXpXpXpXiXpXpXiXiXpXpXpXiXpXpXpXpXpXiXpXiXiXpXpXpXpXpXpXpXpXiXiXpXpXiXpXpXpXiXpXpXiXiXpXpXpXpXpXiXpXiXpXpXpXiXpXpXiXiXpXpXpXpXpXiXpXpXiXpXpXpXiXpXpXiXpXpXpXpXpXiXpXpXpXiXpXpXiXiXpXpXpXpXiXiXpXpXpXiXpXiXpXpXpXiXpXpXiXiXpXpXpXpXiXiXpXpXiXpXpXpXpXiXpXpXiXiXiXpXiXpXpXpXpXiXpXiXpXpXpXiXpXpXiXpXiXpXpXpXpXiXpXpXpXpXiXpXiXpXpXpXpXiXpXiXiXpXpXpXpXiXpXiXiXpXiXiXpXpXpXiXpXpXpXiXpXiXpXiXpXpX", -"iXpXiXpXpXpXpXiXpXiXiXpXiXpXpXpXiXiXpXiXpXiXpXiXpXiXiXpXiXpXiXpXpXiXpXpXpXiXpXpXiXiXpXiXiXpXiXpXpXiXiXpXiXpXpXpXiXpXiXpXpXiXpXiXiXpXpXpXpXiXiXpXpXiXpXiXiXpXiXpXiXiXpXpXpXiXpXiXpXiXpXiXpXiXpXiXpXiXpXpXpXiXiXpXiXpXiXpXpXiXpXpXiXpXpXiXiXpXiXpXiXpXiXpXpXiXiXpXiXpXiXpXpXiXpXiXiXpXpXpXpXiXpXiXiXiXpXpXiXpXpXpXiXpXpXiXpXiXpXiXpXiXpXiXpXiXiXpXiXpXiXpXpXiXpXpXiXpXiXpXpXiXiXpXpXpXpXiXpXiXiXpXpXiXiXpXiXpXpXpXiXpXpXpXpXiXpXiXiXiXpXiXiXpXiXpXiXpXpXiXpXpXpXuXr.+ X X # r.9XpXiXiXiXpXiXpXiXpXiXpXpXiXpXiXpXpXpXiXpXiXpXpXpXiXpXpXiXpXiXpXpXiXpXiXpXiXiXpXiXpXiXpXpXiXpXpXiXpXiXpXiXpXpXpXpXiXiXpXiXpXpXpXpXpXpXiXpXpXiXiXpXpXpXiXpXpXiXpXpXiXpXiXpXiXiXpXiXpXiXpXpXiXpXpXiXiXiXpXpXpXiXpXiXpXiXpXiXpXiXpXpXiXpXpXiXiXpXpXpXiXpXpXpXiXpXpXiXpXpXiXpXpXpXiXpXiXpXiXpXiXiXpXiXpXpXpXiXiXpXiXpXiXpXpXiXpXpXpXpXpXpXiXpXpXiXiXpXiXiXpXpXpXiXpXpXiXpXiXpXiXiXpXiXpXiXpXiXpXiXpXiXpXiXpXpXpXpXiXiXpXiXpXpXpXpXiXpXpXpXiXpXpXiXiXpXiXiXpXiXpXiXiX", -"iXiXpXiXiXiXiXpXiXpXiXpXpXiXiXiXiXpXiXpXiXpXiXpXpXiXpXiXpXiXiXiXiXpXiXiXpXiXiXpXiXpXiXpXpXiXpXiXiXpXiXpXpXiXiXiXpXiXpXiXiXpXiXpXpXiXiXiXiXpXiXpXiXpXiXpXiXiXpXiXiXpXiXiXiXpXiXpXiXpXiXpXiXpXiXpXiXpXiXiXpXiXpXiXpXiXiXiXpXiXiXiXpXiXiXpXpXiXpXiXiXiXpXpXiXpXiXpXpXiXpXiXiXpXiXpXpXiXiXiXiXpXiXpXiXpXiXiXpXiXiXiXpXiXiXpXiXpXiXpXiXpXiXpXiXpXpXiXpXiXiXiXiXpXiXiXpXiXpXiXiXpXiXpXiXiXiXpXiXpXiXpXiXpXiXpXpXiXiXiXpXiXiXiXiXpXiXpXiXpXiXpXpXiXpXiXiXiXiXpXiXiXiXiXpX9X[ o X X o [ 9XpXpXiXpXpXpXiXpXiXiXiXpXiXiXpXiXpXiXiXpXiXiXpXiXiXpXiXiXiXiXpXiXiXiXpXiXpXiXpXpXiXpXiXiXiXiXpXiXiXiXpXiXpXpXiXiXiXiXpXiXpXpXiXiXiXiXiXpXiXiXiXiXpXiXiXiXpXiXiXpXiXiXpXiXpXiXpXpXiXpXiXiXiXiXpXiXiXiXpXpXiXiXiXpXiXpXiXpXiXpXiXpXiXpXiXiXiXiXpXiXiXiXpXiXiXpXiXiXiXiXiXiXpXiXiXpXiXiXpXiXpXiXpXpXiXpXiXiXpXiXpXiXpXpXiXiXiXpXiXiXpXiXiXpXiXiXpXiXpXiXpXpXiXiXiXpXiXiXpXiXpXiXpXpXiXpXiXiXiXpXiXpXiXiXiXpXiXiXiXiXpXiXiXpXiXiXiXiXpXiXiXpXiXiXpXiXpXiXpXpXiXpXiXiXpX", -"pXiXiXpXiXiXiXiXiXpXiXiXiXiXpXiXpXiXiXiXiXiXiXiXiXpXiXpXiXpXiXpXiXiXiXpXiXpXiXiXiXiXiXiXiXpXiXpXiXpXiXiXiXiXpXiXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXpXiXiXpXpXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXpXiXpXiXpXiXpXpXiXiXiXiXiXpXiXiXiXiXpXiXpXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXpXiXiXpXpXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXpXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXpXiXiXiXpXiXiXiXiXpXiXiXiXpXiXiXiXiXiXpXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiX9X[ . O [ 8XiXiXiXiXiXpXiXiXiXiXpXiXpXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXiXpXiXpXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXiXiXiXiXiXpXiXpXpXiXiXpXiXiXiXiXiXpXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXiXiXiXpXiXiXpXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXpXiXpXiXiXpXiXpXiXiXiXiXpXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiX", -"iXiXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXpXiXpXiXpXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXpXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXpXiXiXpXiXiXiXiXpXiXpXiXpXiXpXiXiXiXiXiXiXiXpXiXpXiXpXiXiXiXiXiXiXpXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXiXiXiXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXpXiXpXiXiXiXpXiXpXiXiXiXiXpXiXiXiXiXiXiXiXiXpXiXpXpXiXpXiXiXiXiXpXiXiXiXpXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXpXiXiXiXiXpXiXpXiXiXpXiXiXiXpXiXiXiX8XE X X X E 8XiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXpXiXpXiXpXiXpXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXpXiXpXiXpXiXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXpXiXiXiXiXpXiXpXiXiXiXpXiXpXiXpXiXiXpXiXiXiXpXiXiXiXpXiXpXiXiXiXiXpXiXiXiXiXpXiXpXiXpXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXpXiXpXiXiXiXpXiXiXpXiXiXiXpXiXpXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXpXiXpXiXiXpXiXpXiXpXiXpXiXpXiXiXiXpXiXiXiXpXiXpXiXiXiXiXiXiXiXiXiXiXiXiXpXiXpXiXiXiXiXiXpXiXpXiXpXiXpXiXiXpXiXpXiXpXiXiXpXiXiXpX", -"iXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXaX{.E X X E 8XiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpXiXiXiXiXiXiXiXiXiXiXiX", -"iXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXtXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXtXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXpX{.H X X X . H {.iXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiX", -"tXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXtXiXiXiXiXiXtXiXiXtXtXiXiXtXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXtXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXtXiXiXiXiXiXiXiXtXtXiXiXiXiXtXiXiXiXiXiXiXtXiXiXiXiXiXiXtXiXtXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXtXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiX{.H X G {.iXiXiXiXiXiXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXtXiXiXiXiXtXiXiXiXiXiXiXiXiXrXiXiXiXiXiXiXiXiXtXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXtXiXiXiXtXiXiXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXtXtXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXtXiXiXiXiXtXtXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXtXiXtXtXiXiXiXiXtXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXiXtXiXiXtXtXiXiXiXiXiXiXiXiXiXiXiX", -"iXiXiXiXtXiXtXtXiXiXiXiXtXiXtXtXiXtXtXiXtXiXiXtXtXiXiXiXtXiXiXtXtXiXtXtXiXtXtXiXtXiXiXtXtXiXtXtXtXtXiXtXiXtXtXiXtXtXiXtXtXiXtXtXtXtXiXtXiXtXtXiXtXtXiXtXiXtXtXiXtXtXtXiXtXiXiXtXtXtXtXiXtXtXiXtXtXiXtXtXiXtXiXtXiXiXtXiXtXtXtXiXiXiXtXiXtXiXtXtXiXiXtXiXiXiXtXtXtXiXtXtXtXiXtXtXiXiXtXiXtXiXtXtXiXiXtXiXiXtXtXiXtXiXtXiXtXtXiXiXiXtXiXiXtXiXiXtXiXiXtXiXtXiXiXtXtXiXtXiXiXtXiXiXtXtXiXtXiXiXtXtXtXtXiXtXiXtXtXiXtXtXiXtXtXiXtXtXiXiXiXtXiXtXtXiXtXiXiXtXiXiXiXiXrXiXtXiXrXiXtXiXiXiXiXtXtX[.n X X n [.iXiXiXtXiXtXtXtXiXtXiXtXtXiXiXtXiXtXiXtXiXtXtXiXtXtXiXtXtXtXiXtXtXiXtXtXiXtXtXiXtXtXiXtXtXiXtXiXiXtXiXiXtXiXiXrXiXiXtXtXiXiXiXiXiXiXtXiXrXiXiXiXiXiXtXiXiXiXrXiXiXrXiXrXiXiXrXiXiXrXiXrXiXiXtXiXiXtXiXiXtXiXiXtXiXtXiXiXtXiXtXtXiXtXtXiXtXiXtXiXiXtXiXiXtXiXtXtXiXtXtXiXiXtXiXtXtXiXtXtXiXtXiXiXtXiXiXtXiXiXtXiXiXtXiXiXtXtXtXiXtXtXiXtXtXiXtXtXiXtXtXtXiXiXiXtXiXtXiXtXtXtXiXiXtXtXiXiXiXtXiXtXtXiXtXtXiXtXiXtXtXiXtXtXiXtXtXiXtXiXtXtXiXtXtXiXtXtXtXiXtXtXiXtXiXtXiXtXtXiXtXtXiXtXtXiXtX", -"tXiXiXtXiXtXtXiXiXtXiXiXiXtXiXiXtXiXtXiXtXiXiXiXiXtXiXiXtXtXiXtXtXiXtXiXtXiXiXtXtXiXiXtXiXtXtXtXiXtXtXiXtXtXiXtXtXiXtXtXiXiXiXiXiXtXiXtXiXiXtXiXtXiXiXiXtXiXiXtXiXtXtXiXtXiXtXiXiXiXiXtXiXiXtXiXiXtXiXiXtXiXiXiXiXtXtXiXtXiXtXiXtXiXiXtXiXiXiXtXiXtXiXtXiXtXtXiXtXiXiXtXiXiXtXiXiXtXiXiXiXtXtXiXtXiXiXiXiXiXiXtXiXtXiXtXiXiXtXiXiXtXiXiXiXtXtXiXtXiXtXiXtXiXiXiXtXiXiXiXtXtXiXtXtXtXiXtXiXtXtXiXiXtXtXiXtXtXiXiXiXtXiXiXiXtXtXiXtXiXiXiXiXiXiXtXiXtXtXiXtXiXtXiXtXiXtXtXiXiXiXtXiXiXiXtXiXtXtX[.r n [.tXtXtXiXiXiXtXiXtXiXtXiXtXtXiXtXiXiXtXiXiXiXtXiXtXiXiXtXiXiXiXiXtXtXiXtXiXtXtXiXtXtXiXtXiXtXiXiXtXiXiXiXtXtXiXtXiXiXiXiXiXiXtXiXrXiXrXiXiXrXiXtXiXtXiXtXiXiXtXiXtXtXiXtXiXtXiXiXrXiXrXiXiXiXiXiXtXiXiXiXtXiXiXtXiXtXiXtXiXiXiXtXtXiXtXtXiXtXtXiXiXiXtXtXtXiXiXtXtXiXtXiXtXiXiXiXiXtXiXiXiXtXtXiXiXtXiXtXiXtXtXiXtXiXtXiXtXiXiXiXtXtXiXtXiXtXtXiXtXiXtXtXtXiXiXtXiXiXiXiXiXiXtXiXtXtXiXtXiXtXiXtXtXiXiXiXtXiXtXiXtXuXiXiXiXtXtXiXtXtXiXtXiXtXiXiXtXtXiXtXtXiXtXiXtXtXiXtXiXiXiXtXiXiXtXiXiXiXtX", -"tXtXtXiXtXiXiXtXtXiXtXtXiXtXtXtXtXiXtXtXtXtXtXtXtXiXtXtXtXiXtXiXtXtXiXtXtXtXtXiXiXtXtXiXtXiXtXtXiXtXiXtXtXiXtXiXtXtXtXiXiXiXtXtXtXiXiXtXtXtXtXtXiXtXtXtXtXtXtXiXtXiXtXiXtXiXtXtXtXtXtXiXtXtXtXtXiXtXtXtXtXtXtXiXtXiXtXiXtXtXiXtXtXtXtXiXtXtXiXtXtXtXtXiXiXtXiXtXtXtXtXiXtXtXtXtXtXiXtXtXiXtXiXtXiXtXtXtXtXtXtXiXtXiXtXiXtXtXtXtXtXiXtXtXiXtXiXtXtXtXiXtXiXtXtXtXtXtXtXtXtXiXtXiXtXtXtXiXiXtXiXtXiXtXiXtXtXiXtXtXtXiXtXtXiXtXiXtXtXtXtXtXtXtXtXiXiXtXiXtXiXtXtXtXiXtXtXiXtXtXtXiXtXtXtXiXtXiXtXtXrX[.8 X w [.tXiXtXtXiXtXtXtXiXtXiXtXiXtXiXtXtXtXtXtXiXtXtXiXtXtXtXtXtXtXtXtXtXtXiXtXiXtXiXtXtXiXtXiXtXiXtXtXtXtXiXtXtXiXtXiXtXiXtXtXtXtXtXtXiXiXiXiXiXiXtXtXiXiXtXiXtXtXtXtXiXtXiXtXiXtXtXiXtXiXiXiXiXiXrXiXrXtXiXtXtXiXtXtXtXtXtXiXtXiXtXtXtXtXiXtXiXtXtXtXiXtXtXiXtXtXtXtXtXtXiXtXiXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXiXtXtXiXtXiXiXtXiXtXtXtXtXiXiXtXtXtXiXtXtXiXiXtXtXtXtXtXiXtXtXtXtXtXtXiXiXtXiXtXiXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXiXtXiXtXiXtXtXtXtXiXiXtXtXiXtXiXtXiXtXiXtXtXtXtXtXtXtXiXtXtXiXtX", -"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXiXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXK.6 X 6 K.eXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXiXtXtXtXtXtXtXrXrXiXrXrXiXrXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXrXrXiXrXiXrXrXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX", -"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXtXtXtXF.6 6 F.uXwXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXtXtXtXtXtXrXiXrXiXtXtXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXiXrXiXrXiXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX", -"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXeXG.1 X 1 G.tXtXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXrXtXtXtXtXtXtXtXtXtXtXiXtXtXtXtXtXtXtXiXrXiXiXiXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXiXtXtXtXiXtXtXtXtXtXtXtXtXtXtXtXtXtXiXiXtX", -"tXrXtXtXtXrXtXtXtXrXtXrXrXtXtXtXtXtXtXrXtXtXrXtXtXrXtXtXtXtXtXrXrXtXtXrXtXtXrXtXtXtXtXrXtXtXrXtXrXtXrXtXtXtXtXtXtXrXtXrXrXtXtXtXrXtXtXrXtXtXtXtXtXtXrXtXtXrXtXtXtXrXtXtXtXtXrXtXrXtXrXtXtXtXrXtXtXtXrXtXtXrXtXtXtXtXtXrXtXtXrXtXtXtXrXtXtXrXrXtXtXrXtXrXtXtXrXtXtXrXtXtXtXtXtXtXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXtXtXtXtXrXtXtXrXtXtXrXtXtXtXtXtXrXtXtXrXtXtXtXrXtXrXtXrXtXtXtXtXtXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXrXtXtXrXtXtXtXrXtXtXrXtXrXtXrXtXtXrXrXtXtXtXrXtXrXtXrXtXtXtXrXwXtXe.- - e.tXwXrXtXtXrXtXtXrXtXtXrXtXtXtXrXtXtXrXtXtXtXtXrXtXrXtXrXtXtXrXrXtXtXrXtXrXtXtXrXtXtXtXtXrXtXrXrXtXrXtXrXtXtXtXtXtXrXtXtXrXtXrXtXtXtXrXrXtXrXtXtXrXtXrXtXtXrXtXrXtXrXtXtXtXtXrXtXrXrXrXrXrXrXtXtXrXrXrXtXrXrXrXiXrXtXrXtXrXrXtXtXtXtXtXtXrXtXtXrXtXtXtXrXtXrXtXtXrXtXtXtXtXtXrXtXtXtXtXtXtXtXrXtXrXtXrXtXrXtXrXtXrXtXtXtXtXtXrXtXtXrXtXrXtXrXtXtXrXtXtXrXtXrXtXrXtXtXtXrXtXtXtXtXtXrXtXtXrXrXtXtXrXrXtXtXrXtXtXtXrXtXtXtXtXtXtX@XtXtXtXtXtXtXtXtXtXtXtX@XtXtXtXtXtXtXtXtX@X@XtXtXiXtXtXiX@XtXtXtXtXtXtXtXtXtX@XtXtX", -"rXrXtXrXtXrXrXrXtXtXrXtXrXtXtXrXrXtXrXtXtXrXtXrXrXrXtXrXtXrXrXrXtXtXrXtXrXtXtXrXtXtXtXrXtXrXtXrXtXrXrXtXrXtXrXtXrXtXrXtXrXtXtXrXrXtXtXtXrXtXtXtXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXtXtXrXrXtXrXtXtXrXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXtXtXrXtXtXrXtXrXtXtXrXrXtXtXrXtXtXtXrXrXtXrXtXrXtXrXtXrXtXrXtXrXtXrXtXrXtXtXtXrXtXrXtXrXtXrXtXrXtXtXrXrXtXrXtXtXrXrXtXrXrXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXrXrXtXrXtXrXtXrXtXrXtXrXtXtXtXrXtXrXtXrXtXrXtXrXtXtXtXrXtXrXtXtXrXtXtXtXrXrXtXrXtXtXrXtXrXtXtXtXrXrXtXrXtXtXrXrXrX9Xe.- - e.eXrXtXrXrXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXrXrXrXtXrXtXtXtXrXrXtXrXtXtXrXtXtXrXtXrXtXtXrXtXtXtXrXtXtXtXtXtXrXtXtXrXtXrXtXrXtXrXtXrXtXtXrXrXtXtXtXrXtXrXtXrXtXtXrXtXtXtXrXtXrXtXtXtXrXtXtXrXtXtXtXtXrXtXtXrXtXiXrXtXrXrXrXrXtXrXtXrXtXtXrXrXtXrXtXtXrXtXrXtXrXtXtXrXrXtXtXtXtXrXrXrXtXrXtXrXtXtXrXrXtXtXtXrXtXtXtXrXtXtXtXrXtXrXrXrXtXrXrXtXrXtXtXrXrXtXtXtXtXrXtXtXrXtXtXtXtXrXtXrXtXrXrXrXtXrXtXrXtXrXtXrXtXtXtXrXtXrXtXtXtXtXtXtXtXtXtX@XtXtX@XtXtXtXtXtXtXtXtXtXtXtXtXiXtX@XtXiXtXtX@X@XtXtXtX@XiXtXtX@XiX@XiXtXtX@XiX", -"tXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXtXrXrXtXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXwX8Xe.# $ 4.eXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtX@XtXtX@XtXtXtXtXtXtXtXtX@XtXtX@XtXtXtX@XtXtX@X@XtXiXtXiX@XtXtXtXtXiX@XtXiX@XiX@XtXtXiX@XiX@XtX", -"rXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXtXrXrXrXrXtXrXrXrXrXtXrXtXrXrXrXrXtXrXrXtXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXtXrXrXrXrXrXtXrXrXrXrXtXrXtXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXtXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXtXrXrXrX}.E E 8XrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXtXrXrXrXtXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXtXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXtX", -"rXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXiXtXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrX", -"rXrXrXrXrXrXrXrXrX@XrXrXrXrXrXrXrXrXrXrXrXrXrXwXwXrXrXwXrXrXrXrXrXrXrXwXwXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXwXrXwXrXrXrXrXrXrXrXwXrXwXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXwXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXwXrXwXrXrXwXwXrXrXrXrXwXrXrXrXrXrXrXrXwXrXwXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXwXwXrXrXrXrXrXwXrXrXwXrXrXrXrXrXrXrXwXrXwXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXwXrXrXwXrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXwXrXwXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXwXrXrXrXrXrXrX@XrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXwXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXwXrXrXrXrXrX", -"rXtX@XrXrXrXrXrXrXrXrXrX@XrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXwXrXrXwXrXrXrXrXrXrXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXwXrXrXrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXwXrXrXwXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXwXrXrXrXwXrXrXwXrXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXeXrXrXrXrXrXrXrXrXrXwXrXrXrXrXwXrXwXrXrXwXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXwXrXwXrXrXwXwXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXrXrXwXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXwXrXrXrXwXrXrXwXrXwXrXrXrXrXrXrXrXrXwXrXrXrXrXrXeXwXrXrXwXrXrXrXrXrXwXrXrXrXwXrXrXwXrXrXrXrXwXrXrXwXrXrXrXwXrXrXrXwXrXrXrXrXwXrXrXwXrXrXrXwXrXrXrXwXrXrXwXwXrXrXrXwXrXrXwXwXrXrXrXrXwXrXrX@XrXtX@XrXrXrXrXrXrXrXrXrXrXrX@XrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXwXrXrXwXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrX", -"rX@XwXtXwXtXrX@XrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXrXrXrXrXrXrXwXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXwXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrX@XrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXwXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXwXrXwXrXrXeXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXwXrXrXrXrXrXrXrXwXrXrXwXrXrXrXrXrXrXtXrXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXwXrXwXrXrXrXrXwXrXwXrXrXrXrXwXrXrXrXrXrXrXrXrXrXwXrXwXrXrXrXrXrXrXrXrXrXrXwXrX", -"rXrXtXwXwXwXrXrXrX@XrXrXrXrXrX@XeXrXrXwXwXrXwXwXrXwXrXwXrXrXrXrXwXrXwXrXrXwXrXwXrXwXrXrXrXwXwXrXwXrXwXrXrXwXrXrXrXrXrXrXrXwXrXwXrXwXwXrXwXrXwXrXwXrXrXwXrXwXrXrXrXwXrXwXrXrXwXrXrXwXwXrXwXrXwXrXrXwXrXwXrXrXeXrXwXrXwXrXrXwXrXwXrXrXrXwXwXrXwXrXwXrXwXrXrXwXwXrXrXrXrXrXrXwXrXwXrXwXwXrXwXrXrXwXrXrXrXwXrXwXrXrXrXrXrXrXrXwXrXwXwXrXwXrXrXwXrXwXrXrXrXrXwXrXwXrXrXrXwXrXrXwXrXwXwXrXwXrXrXwXrXwXrXwXrXwXwXwXrXrXrXrXwXrXrXwXrXwXwXrXwXwXrXwXrXwXwXrXwXrXwXwXrXrXrXrXwXrXrXwXrXwXwXrXwXrXrXwXrXwXrXrXrXwXrXrXrXrXwXrXwXrXrXwXwXrXwXwXwXrXrXrXrXrXwXrXrXwXrXwXrXwXrXrXrXrXwXrXrXwXrXwXrXrXrXwXwXrXrXrXrXrXrXwXrXrXrXwXwXrXrXwXrXrXrXrXrXrXwXrXrXwXeXrXwXrXwXrXwXrXrXrXrXrXrXrXwXrXrXrXrXrXwXeXwXrXrXrXwXrXrXwXrXwXwXrXwXrXrXwXrXwXrXrXrXrXwXrXwXrXrXrXwXrXrXwXrXrXwXwXrXwXwXrXrXrXrXwXwXrXwXrXwXrXwXrXrXwXrXrXrXwXrXwXrXwXrXrXrXwXrXwXrXwXrXrXrXwXrXwXwXrXwXrXrXwXrXwXrXwXrXrXrXrXrXwXwXrXrXrXrXrXrXwXwXrXrXrXrXrXrXrXwXrXrXwXwXrX@XrXrXwXwXrXeXwX@XrXrX@XrX@XrXrXwXrXwXrXrXrXwXrXrXrXrXrXwXrXrXwXrXrXrXrXwXrXrXrXwXrXwXrXwXrXwXwXwXrXrXrXrXwXrXwXwXrXwXrXwXrXwXrX", -"wXrX@XrXtXeXrXrXrX@X@XrXrXrXrXrXrXwXwXrXrXwXrXrXrXrXwXrXwXwXrXrXrXwXrXwXwXrXwXrXrXrXrXrXwXrXrXwXrXrXwXwXwXrXwXwXwXrXwXrXrXwXwXrXrXrXwXrXrXwXrXwXrXrXwXrXwXwXrXwXwXrXrXrXwXrXrXwXrXrXwXrXrXwXrXwXrXrXwXrXwXwXrXrXrXwXrXwXwXrXwXrXrXwXwXrXwXrXwXrXrXrXrXrXwXrXwXwXwXwXrXrXrXrXwXrXwXrXwXrXrXwXwXrXrXwXrXwXwXrXwXrXwXwXrXrXrXrXwXrXrXwXrXwXwXrXrXwXrXwXwXrXrXwXrXwXwXwXrXrXwXrXwXrXrXwXrXwXwXrXwXrXrXrXrXrXrXwXrXwXwXwXrXrXwXrXrXrXrXwXrXrXrXrXwXrXwXrXrXrXrXwXrXwXwXwXrXrXwXrXwXrXrXwXrXwXwXrXrXwXrXwXrXwXwXrXwXrXrXrXwXrXwXwXrXrXrXwXwXrXrXrXrX@XwXrXrXwXwXrXrXrXwXwXrXrXrXrXwXrXwXwXrXwXwXrXrXwXrXwXrXrXwXrXrXwXwXrXwXrXwXrXwXwXwXrXwXrXrXrXwXrXrXwXwXrXrXwXeXwXwXrXwXrXrXrXrXwXrXwXwXrXrXwXwXrXwXwXrXrXwXrXwXrXrXwXrXwXwXrXwXrXrXwXwXrXwXrXwXrXwXwXrXrXwXrXwXwXrXwXwXrXrXwXwXrXrXrXwXrXrXwXrXwXwXrXwXrXrXwXrXwXwXrXwXrXrXwXwXrXwXrXwXrXrXwXwXrXwXrXrXwXwXrXrXwXwXrXwXrXrXwXwXrXwXrXrXwXrXwXwXrXwXrXrXwXrXwXwXrXwXrXrXwXrXrXrXrXrXrX@XrXtXtXwXtXrXrXrXrX@XrX@XrXwXrXrXrXwXrXrXwXwXwXrXrXrXrXwXrXwXrXwXrXrXrXwXwXrXwXwXrXrXwXrXrXrXrXwXwXrXrXwXrXrXwXrXwXwXrXrXwX", -"wXrXrXwXwXwX@XrX@XrXrXrX@X@XrX@XwXrXwXwXrXwXwXwXwXwXrXwXwXrXwXwXwXrXwXrXwXwXrXwXwXwXwXwXwXwXwXrXwXwXwXrXrXwXwXrXwXwXrXwXwXrXwXwXwXwXrXwXwXrXwXrXwXwXrXwXwXrXwXrXwXwXwXwXrXwXrXwXwXwXrXwXrXwXwXrXwXwXrXwXwXrXwXwXwXrXwXrXwXwXrXwXwXrXwXwXrXwXrXwXwXwXwXwXrXwXwXrXwXrXwXwXwXwXrXwXwXwXrXwXwXrXwXwXrXwXwXrXwXwXrXwXwXrXwXwXwXwXrXwXwXrXwXrXwXwXrXwXwXrXwXwXrXwXrXwXwXrXwXwXrXwXwXrXwXeXwXrXwXwXrXwXwXwXwXwXwXrXwXrXwXrXwXwXwXwXwXwXrXwXwXwXwXwXwXwXeXwXwXwXwXrXwXrXwXrXwXwXrXwXwXrXwXrXwXrXwXwXrXwXwXrXwXrXwXwXrXwXwXwXrXwXwXrXwXwXrXwXrXwX@XrX@XrXrXwXwXrXwXwXwXwXwXrXwXwXwXwXrXwXwXrXwXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXrXwXwXrXwXwXrXwXwXwXwXwXwXrXwXwXrXwXrXwXwXwXrXwXwXwXwXrXwXrXwXwXrXwXrXwXwXrXwXwXrXwXrXwXwXeXwXrXwXwXrXwXwXrXwXwXrXwXrXwXwXrXwXwXrXwXwXrXrXwXrXwXwXrXwXwXwXwXrXwXwXrXwXrXwXrXwXwXwXrXwXrXwXwXrXwXwXrXwXrXwXwXrXwXwXrXwXrXwXwXrXwXrXwXwXrXwXwXrXwXwXrXwXwXrXwXrXwXwXrXwXrXrXwXrXwXwXrXwXwXrXwXrXwXwXwXwXwXwXrXrXwX@XwXwXwXrX@XrX@XrXrX@XrXeXwXwXwXwXwXwXrXwXrXwXwXwXwXrXwXwXwXrXwXwXwXwXrXrXwXwXwXrXwXwXwXwXwXwXrXwXwXrXwXwXrXwXrXwXwXrXwX", -"wXrXwXwXwXwXeXwXrX@XwXrX@XwXrX@XwXrXwXrXwXwXrXwXwXwXrXwXrXwXeXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXeXwXwXrXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXrXwXeXwXwXwXwXwXwXwXrXwXwXrXwXwXwXwXwXwXrXrXwXrXwXwXrXwXeXwXwXrXwXrXwXwXwXwXwXwXrXwXwXrXwXwXrXwXwXwXwXwXwXwXrXrXwXwXrXrXeXwXwXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXrXwXwXwXwXrXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXrXwXeXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXwXwXrXwXwXrXwXeXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXrXwXrXrXwXrXwXwXwXwXwXwXwXrXwXwXrXwXwXwXwXwXwXwXrXwXwXwXrXwXwXwXwXwXwXrXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXrXrXwXwXwXrXwXeXwXwXwXwXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXrXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXrXwXrXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXrXwXwXwXwXwXrXwXeXwX@XrXwXrX@XrX@XrXwXwXwXwXwXrXwXwXwXwXrXwXrXwXwXeXrXwXwXrXwXrXwXwXrXwXrXwXwXrXwXrXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwX", -"wXwXwXrXrXwXwXwXwXrXwXrXrXwX@XrXwXwXwXwXrXwXwXwXrXwXwXwXwXwXwXwXwXwXrXwXwXwXwXrXwXrXrXwXwXwXrXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXwXrXwXrXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXeXwXrXwXwXwXwXwXwXwXwXwXwXwXrXrXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXrXwXrXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXwXrXwXrXwXwXrXwXwXwXwXwXwXwXwXwXrXwXwXwXrXwXwXrXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXrXwXwXwXwXrXwXwXrXwXwXwXwXrXwXrXwXwXwXwXwXwXwXwXwXwXrXwXwXrXwXwXwXwXrXwXwXwXwXwXwXwXeXwXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwXwXwXrXwXwXwXwXwXrXwXwXwXrXwXwXwXwXrXwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXrXwXwXwXwXwXwXwXwXrXwXwXrXwXwXrXwXrXwXwXwXwXwXwXrXwXwXwXrXwXrXwXwXrXwXwXwXwXrXwXwXwXwXwXrXwXrXwXwXwXwXwXrXwXwXrXwXwXrXwXrXwXwXwXwXwXrX@XwXrXrX@XrXwXrXwXrXwXwXwXwXrXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXrXwXwXwXwXwXwX", -"wXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXwXwXwXwX@X@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX", -"wXwXwX@XwXwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXrXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX", -"wXwX@XwX@XwXwXwXwXwXwX@X@X@XwXwXwXwX@X@X@XwXwXwX@XwXwX@XwX@XwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXwXwX+XwXwXwX+XwXwXwXwXwXwXwXwX+XwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwX+X@X@XwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwX+XwXwXwXwX+XwXwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwX+XwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwX+XwXwXwX@XwXwX+XwXwXwXwXwX@XwXwXwX@XwXwXwX@XwXwXwX+XwXwXwXwXwX+XwXwX+XwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwX+XwXwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXwX@XwX+XwXwXwXwXwXwX+XwXwX+XwXwXwX+XwXwX+XwX+XwXwXwXwXwXwXwXwX+XwXwX+XwXwX+XwXwX+XwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwX+XwXwXwXwX+XwXwX+XwXwXwXwX+XwXwX+XwXwXwX+XwXwXwXwX@X@XwXwXwXwXwXwX@X@X@XwXwXwXwX@X+X@XwXwXwX@XwXwX@XwX@XwXwXwXwXwX+XwXwX+XwXwXwXwXwX+XwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX", -"@XwX@XwXwXwX@XwX@X@XwXwXwXwXwX@X@XwXwXwXwXwX@XwXwX@XwXwXwX@XwX@XwXwX+XwX+XwXwXwXwXwXwXwX+XwX+XwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwX+XwX+XwX+XwXwXwXwX+XwX@XwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwX+XwXwXwX+XwXwXwXwX+XwXwXwXwX+XwXwXwXwXwXwX@X@XwXwXwXwXwX+XwX+XwXwX+XwXwXwXwXwXwX+XwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwX@XwXwXwXwXwXwX@XwXwXwX@XwXwXwXwXwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwX+XwXwXwX+XwXwXwXwX+XwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwX+XwX+XwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwXwXwX+XwXwXwX+XwXwX@XwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwX+XwXwX+X@X+XwXwXwXwXwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX@XwXwXwXwX@XwX@X@XwXwXwXwXwX@X@XwXwXwXwXwX@X@XwX@XwXwXwXwXwX@XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwX", -"wX@XwX@XwX@XwXwXwX@X@XwX@XwX@XwX@XwX@XwX@XwXwX@XwX@X@X@X@X@X@X@X+XwXwXwXwXwXwX+X+XwXwXwXwXwXwXwX+XwX+XwX+XwXwXwXwXwXwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwX@XwX@XwX+XwXwXwX+XwXwXwX+X+XwXwX+XwXwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwXwX+XwX+X+XwXwXwXwXwX@X@XwX+XwX+X+XwXwX+XwX+XwX+X+XwXwXwXwXwXwXwX+XwXwXwXwXwX@XwX@XwX@XwX@XwX@XwX+XwXwXwXwXwXwXwX+XwXwXwX+XwXwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwXwXwXwXwXwX+XwX+X+XwX+XwXwXwX@XwXwXwXwX+XwXwX+XwXwX+XwXwX+XwXwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwX@X+XwXwXwX@XwXwX@X@XwXwX@X@XwX@X@X@XwX@X@XwX+X+XwXwXwXwXwXwXwXwXwX+XwX+XwXwX+XwX+X+XwXwXwXwXwXwXwXwX+X+XwXwX+XwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwXwXwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwXwX+XwX+X+XwXwXwXwXwX@X@XwXwX@XwXwXwX+XwX+X+XwXwXwX+XwXwX+XwXwXwXwXwXwXwX+XwX+XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX+XwX+X+XwX+XwXwXwXwXwXwXwX+XwXwX+X+XwXwXwXwXwXwXwX+XwXwXwXwXwXwX+XwX+XwX+X+XwXwXwXwX@X@X@XwX@XwX@XwX@X@XwX@XwX@XwX@XwX@XwX@XwXwXwX@XwX@X@XwX@X@X@XwX+XwXwX+XwXwXwXwXwX+XwX+X+XwXwXwXwXwX+XwXwX+XwX+XwX+XwXwXwXwXwX", -"@XwX@X@X@X@X@X@X@X@XwX@X@X@X@X@X@XwX@X@X@X@X@X@X@X@XwX@X@X@X@X@XwX+X+XwX+XwX+XwXwX+X+XwXwX+X+XwXwXwX+XwXwXwX+X+XwX+X+XwX+XwX+XwXwX+XwXwX+XwXwXwX+X+XwX+XwX@X@X@XwX+X+XwXwX+X+XwXwXwXwX+XwX+X+XwX+X+XwXwXwX+XwXwX+XwXwXwX+X+XwX+XwX+XwXwXwX+X+XwX+X+XwX@XwX+XwXwXwXwX+XwXwX+XwXwXwX+X+XwX+X+XwX+XwXwX+X+XwX+XwX@X@X@X@X@XwX@X@X@XwX+X+XwXwX+X+XwXwX+X+XwXwX+X+XwX+XwX+XwXwX+XwXwX+XwXwXwX+X+XwX+X+XwX+X+XwXwXwX+XwXwX+XwX+XwX+XwX+XwX+XwX+XwXwX+XwXwXwX+XwX+XwX+X+X+XwXwXwX+XwXwX+XwXwXwX+X+XwX+XwXwX+X+XwX+X+XwX+X@X@X@XwXwX+X+X@X@X@X@X@X@X@X@X@X@X@XwX@X@X@XwXwXwXwX+X+XwX+X+XwX+XwX+XwXwX+XwXwX+XwXwXwX+X+XwX+X+XwX+XwX+XwXwXwXwXwX+XwX+X+XwXwX+X+XwXwX+X+XwXwX+X+XwXwX+X+XwXwX+X+XwXwX+X+XwX+X+XwXwXwX+XwXwX+XwXwXwX+X+XwX+XwX+XwXwXwX+X+XwX+X+XwX@X@X@X@XwX+XwXwX+XwXwXwX+XwXwXwX+XwX+X+XwXwX+XwX+XwXwX+XwX+XwX+X+XwX+XwX+XwX+X+XwX+XwX+XwXwX+XwXwX+XwX@X@XwX+X+XwXwXwX+XwXwXwX+X+XwX+X+XwXwX+X+XwX+X+XwXwXwX+XwXwXwX+X+XwX@XwX@X@X@X@X@XwX@X@X@XwX@X@X@X@X@XwX@X@X@X@X@X@X@X@XwX@X@X@X@X@X+XwXwX+XwX+X+XwX+XwXwX+XwXwXwX+X+X+XwXwXwX+XwXwX+XwXwXwX+X+XwX+X", -"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XwX+XwX+X+XwX+XwXwX+XwX+X@X@X@X@X+XwX+X+XwX+XwX+XwX+X+XwX+X+XwX+X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+XwX+XwX+XwX@X@X@X@X@X@X@X@X+XwXwX+XwX+XwX+XwX+XwX+XwX+X+X+XwX+X+XwX+XwX+XwXwX+XwX@X@X@X+XwX+XwXwX+XwX+X+XwXwX+XwX+XwX+X+X+XwX+X+XwX+XwX+XwX@X@X@X@X@X@X@X@X+XwX+XwX+XwX+XwX@X+XwX+X+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX@X@X@X@X@X@X@X@X@X@X@X@XwX+XwX@XwX+XwX+X+XwX+XwXwX+XwX+X+XwXwX+X+XwXwX+XwX+XwX+X+X+XwX+XwX+X+XwX+XwX+XwX+XwX+XwX@X@X@X@X@X@X+XwX+XwX+XwX@X@X@X@X@X@X@X@X@X@X@X@X+X+XwX+XwX+XwX+XwX+X+XwX+X+XwX+X@X@X@X@X@X@X+XwX+X@X@X@XwX+XwX+X+XwX+XwX+XwX+XwX+XwXwX+X+XwX+XwX+XwX+X+X+XwX+XwXwX+XwX+X@XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XwX+XwX+X+XwX+XwX@X@X@X@X@X@X@X@X+X+XwX+XwX+XwX+XwX+XwX+XwX+XwX+X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+XwX+X+XwX+XwX+X+XwX+XwX+X+X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+XwX+XwX+XwX@X@XwX+X@X@X@X@X+XwX+XwX+XwX+XwX+XwX+XwX+XwX+XwX", -"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+XwXwX+XwX+X+XwX+XwX@X@X@XwXwX+X+XwX+XwX+XwX+XwXwX+XwX+X+XwX@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XwX+XwX+XwX+XwX+X@X@X@XwX@X@X@X@XwX+X+XwX+XwX+XwX+XwX+XwX+XwXwXwX+XwXwX+XwX+XwX+X+XwX+X@X@X@XwX+XwX+X+XwX+XwXwX+X+XwX+XwX+XwXwXwX+XwXwX+XwX+XwX+X@XeX@X@X@X@X@X@XwX+XwX+XwX+XwX+X@XwX+XwXwX+XwX+XwX+XwX+XwX+XwX+XwX+X+XwXwX+XwX+X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+X@X+XwX+XwXwX+XwX+X+XwX+XwXwX+X+XwXwX+X+XwX+XwX+XwXwXwX+XwX+XwXwX+XwX+XwX+XwX+XwX+X@XwX@X@X@X@XwX+XwX+XwX+X@X@X@XwX@X@X@XeX@X@X@X@X+XwX+XwX+XwX+XwX+XwXwX+X+XwX+XwX@X@X@X@X@X@XwX+XwX+X@X@X+XwX+XwXwX+XwX+XwX+XwX+XwX+X+XwXwX+XwX+XwX+XwXwXwX+XwX+X+XwX+XwX@X+XwX+XwX+XwX+XwX+XwX+XwX+X+XwXwX+XwX+X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XwX+XwXwX+XwX+X@X@X@XwX@X@X@X@XwX+X+XwX+XwX+XwX+XwX+XwX+XwX+XwX@X@X@X@X@X@X@X@X@X@X@X@X@XwX@X@XwX+X+X+XwXwX+XwX+XwXwX+XwX+X+XwX@X@X@X@X@X@X@X@X@X@X@X@XwX+X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XwX+XwX+XwX+XwX+X@X@X+XwX@X@X@XwXwX+XwX+XwX+XwX+XwX+X+XwXwX+XwX+X", -"@X@X@X@XOX@XOX@X@X@X@X@X@X@XOX@X@X@X@XOX@X@X@X@X@X@X@X@X@XOX@X@X+XwXwX+X+X+X+XwX+XwXwX+X+XwX@X+XwX+XwX+X+X+X+XwX+X+XwXwX+X+XwX+X@X@X9X+X@X@X@X@X@X@X@X@X+X@X+X@X+X+XwX+X+X+X+XwX+XwX@X+X@X+X@X+X+X+X+X+X+XwX+XwXwX+XwX+X+X+XwX+XwX+XwXwXwX+X+X+XwX+X+X+X+XwX+XwX+XwX+X+X+XwX+XwXwX+XwX+X+X+XwX+XwX+XwXwXwX+X+X+X@X+X@X+X+X@X+X@X+X+XwX+X+X+X+XwX+XwXwX+X+X+X+XwX+XwX+X+X+XwX+XwX+XwX+XwXwX+X+X+X@X@X@X@X@X+X@X+X@X+X@X+XwX+XwX+X+XwXwX+X+X+X+XwX+XwXwX+X+XwXwX+X+X+X+X+X+XwX+XwX+X+X+XwXwX+XwXwX+XwX+XwXwX+X+X+X@X+X+X+X+X+XwXwX+X+X+XwX+X+X@X+X+X+X@X+X@X+X@X+X+XwXwX+X+X+X+XwX+X+XwXwX+X+XwX+X+XwX+X@X+X+XwXwX+XwX+XwXwX+XwX+X+X+X+XwX+X+X+XwX+XwXwX+X+X+X+XwX+X+XwX+X+X+X+XwX+XwXwX+X+X+X+XwX+XwX+X+X+XwX+XwX+XwX+XwXwX+X+X+XOX@X@XOX@X@XOX@X@X@X@XOX@X+X+X@X+XwXwX+X+X+X+XwX+X+X@X+X+X@X+X@X+X+XwX+XwX+XwX+X+X+XwX+X+XwX+XwX@XOX@X@X@X@X@X@X+X@X@X@X@X+X+X@XwX+XwX+X+X+X+XwXwX+XwXwXwX+XwX+XOX@X@X@X@X+X@X+X+X@X@X@X+XwXwX+X@X@X@X@XOX@XOX@X@XOX@X@X@X@X@X@X@X@X+X@X@X+X+X@X@X@X@X@X@X@X@XOX+X+XwX+X+X+X+XwX+XwXwX+X+X+X+X+X+XwX+X+X+XwX+XwX+XwX+XwXwX+X+X+X", -"@X@X@X@X@X@X@X@X@X@X@X9X@X@X@X@XOX@X@X@X@XOX@X@X@X@X@X9X@X@X@X@X+X+X+X+XwX+X+XwX+X+X+X+X+X+X+X@X+XwX+X+XwX+X+X+XwX+X+X+XwXwX+X+X@X@X@X@X@X@XOX@X@X@X@XOX@X+X@X@X+XwX+X+XwX+X+XwX+X+X+X@X+X@X@X+X+XwXwX+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+XwX+X+X@X+X+X@X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+XwX+X+X@X+X@X+X@X@X+X+XwX+X+XwX+X+XwX+X+X+X@X+X@X+XwX+X+X+XwX+XwX+X+X+X+X+X+X+X+X+XwXOX@X@X@X@X@X+X@X+X@X+X@X+X+X+X@X+X+X+X+X+XwX+XwX+X+X+X+X+X+X+X+X+XwXwX+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X@X+X@X+X+X@X+X+X+X@X@X+X+XwX+X@X@X@X+X@X+X@X+X@X+X+X+X+XwX+X+X+XwX+X+X+XwXwX+X+X@X+X@X@X+X@X+X+X+X+X+X+X+X+X+XwX+XwX+X+XwX+X+XwX+X+X+X+XwX+X+XwX+XwX+X+XwX+X+XwX+X+X+X@X+X@X+XwX+X+X+XwX+XwX+X+X+X+X+X+X+X+X+XwX@X@X@X@X@X@X@X@XOX@X@X@X+X@X@X@X+X+X+X+X+XwX+XwX+X@X+X@X+X@X@X@XwXwX+X+X+X+X+X+X+XwX+X+X+X+X+X+X@X@X@X@X@X@XOX@X@X+X@X+X+X@X@X@X+XwX+X+XwX+X+X+X+X+X+X+X+XwX+X+X@X@X@X@X@X@X+X@X@X+X@X+X@X+X+X@X@X@X@X@X@X@X@X@X@X@X@XeX@X@XOX@X@X+X@X+X+X@X+X@X@X@X@X@X@XOX@X@X+XwX+X+XwX+X+XwX+X+X+X@X+X@X+XeX+X+X+XwX+XwX+X+X+X+X+X+X+X+X+XwX", -"+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX@X@X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X9X+X+X+X+X+X+X+X+X+X+X+X+XeX+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X9X+X+X+X+X+X+X+X+X+X+X+X@X+X+X@X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+XwX+XOX@XOXOX+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X+XwXwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X9X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+XwX+X@X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+XwX+X+XwX+X@X@XOX@X@X@X@X@X@X+X@X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X9X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X@X@X@XOX9X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X9X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+XwX+X+X+XwX+X", -"+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X@X+X+X+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwXwX+X+XwX+X+X+X+XwX+X+X+X+X+X+X+X+X+X@XOXOX@X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+XwX+X+XwX+XwX+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X@X@X@X9X+X+X+X+X+X+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XeX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@XOX@X+X+X+X+X+XwX+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X@X+X+X+XwX+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@XOX@X@XOX@XOX@X+X@X@XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X+X+XwXwX+X+X+XwX+X+XwXwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+XwX+X+X+X+XwX+XoX@XOX@X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X", -"@X+X@X@X+X@X+X+X+X+X@X+X+X+X+X+X+X+X@XOX+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X@XOX@X@X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X@X@X@XOXOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X@XOX@XOX@X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X@X@XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X@X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+XOXwX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X@X@X@X@X@X@X@X@XOX@X@X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX@X+X+X+X+X+X+XOX+X+X+XOX+XwXOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X@X@X@XoX@X@X+X+X+X+X+X+X+X@X+X+X+X+X@XOX+X@X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XwX+X+X+X+X+X+X+X+X", -"+X+XOX@XOX+X+X+X+X+X+X+X+X+X+X+X+X+X@XOX+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+XOX+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX@X@XOX+X+XOX@X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X@X+X+X+XOX+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+XOX+X@XOX@X@XOX@X+X+X+X+X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX@X@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+XOX@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+XOX+XOX@XOXOX@XOXOX@X@XOXOX@X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X@XOX@X+X+X+XOX+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX@X+X+X@XOX+X+X+X+XOX+X+X+XOX+X+X+X+X+X+X+XoX@X@X@X@XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X@X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+XOX+X", -"OX+XOX+XOXOX@XOX@XOX+X+XOX+X+X+X+X+X+X+XOX@XOX@XOX@XOX@X+X+XOX+X+X+X+XOX+XOX+X+XOX+X+X+X+X+X+X+X+XOXOX+X+X+X+X+X+X+X+X+XOX+XOX+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+XOXOX+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+XOXOX+X+X+X+X+XOX+X+X+XOX+XOX+XOX+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+XOXOXOX+X+X+X+XOX+X+X+XOX+XOX+XOX+XOX+X+X+X+XOXOX+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+XOXOX+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+X+XOX+XOX+X+XOX+X+X+X+X+X+XOX+X+X+X+XOX+X+X+X+X+X+X+XOX+X+X+X+X+X+XOX+X+X+X+X+X+X+XOX+X+X+X+X+X+X+XOX+XOX+X+X+XOX+XOX+X+XOX@X+XOX+XOXOX+X+X+X+X+XOX+XOX+XOX+X+X+X+X+XOX+XOX@X+XOX+XOX+X+X+X+X+X+XOX+X+X+X+X+XOX+X+X+X+X+X+XOX+XOXOX+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+XOX+XOX+XOX+X+X@X@X+X+X+X+X+X+X+X+X+X+X+XOX+XOX+X+X@XOX@XOX+X+XOX@X+X+X+X+X+X+X+X+X+XOXOX+X+X+X+X+XOX@XOXOX+X+X+X+XOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOX+X+X+X+XOX+XOX+X@XOX+X+X+X+X+XOX+X+X+X+X+X+X+X+X+X+X+XOXOX+XOX@XOX+X+XOX+X+X+X+X+X+XOX+X+X+XOX+XOX+XOX+X+X+XOX+X+XOXOX+X+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+XOX", -"+X+X+X+X@XOXOX@XOX@X@XOX+X+X+XOX+XOX+XOX@XOX@XOX+XOX@XOX+XOX+X+X+XOX+X+X+X+XOX+X+X+X+XOX+XOX+XeX+X+X+X+X+XOX+XOX+XOX+X+X+X+XOX+XOX+XOX+X+X+XOX+X+XOX+XOXOX+XOX+X+X+X+X+X+XOX+XOX+X+X+XOX+XOXOX+XOX+X+X+XOX+XOX+XOX+X+X+X+X+X+XOX+X+X+X+X+XOX+X+X+X+X+X+XOX+XOX+XOX+X+X+XOX+XOX+XOX+X+X+X+X+XOX+X+X+X+X+X+XOX+X+X+X+X+X+X+X+X+XOX+X+X+X+X+XOX+XOX+X+X+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+XOX+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+X+X+XOX+X+X+X+XOX+X+X+X+XOX+XOX+X+X+XOX+XOX+X+X+XOX+XOX+XOX+X+X+XOX+X+X+X+XOX+XOX+XOX+X+X+XOX+XOX+X+XOX+X+X+X+XOX+X+X+X+X+XOX+XOX@X+X+X+X+X+X+XOX+XOX+X+XOX+X+X+X+XOX+XOX+X+X+X+XOX+X+X+X+XOX+XOX+XOX+XOX+X+XOX+XOXOX+X+XOX+XOX+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+X}.+XOX+XOX+X+XOX+X+X+XOX+X+X+X+XOX+XOX@XOX@X@XOX@XOX+XOX+X+XOX+XOX+X+X+X+X+X+XOX+XOX+X+X+X+XOX+XOX+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+XOX+X+X+X+X+X+X+XOX@X+XOX+XOX+X+X+XOX+XOXOX+XOX+XOX+X+X+X@XOX@XOX@XOXOX@XOX+XOX+X+X+X+X+X+XOX+X+X+X+X+X+XOX+X+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+X+X+XOX+XOX+X+X+X+X+X+X+XOX+XOX+X+X+X", -"OX+XOX+XOX@X@XOX+X+XOX@X+XOX+X+X+X+XOX+XOX@X@XOXOX+XOX+X+XOX+X+X+X+X+XOX+XOX+XOXOX+XOX+X+X+X+X}.OX+XOX+XOX+X+X+X+XOX+XOXOX+X+X+X+X+X+X+XOX+XOX+XOX+X+X+X+XOX+XOXOX+X+X+X+XOX+XOXOX+XOX+X+X@XOX+X+X+XOX+XOX+XOX+X+X+XOX+XOX+XOX+XOX+XOX+X+X+X+XOXOX+XOX+X+X+X+XOX+XOXOX+X+X+XOX+X+X+X+XOXOX+XOX+XOX+XOX+X+X+X+XOXOX+XOX+X@XOX+XOXOX+X+X+X+XOX+XOX+XOX+XOXOX+XOXeX+XOX+XOX+XOXOX+XOX+XOX+X+X+XOX+XOX+XOX+XOX+X+X+XOX+X+X+XOX+X+XOX+X+X+XOX+XOX+XOX+XOXOX+X+X+X+XOX+X+XOX+XOX+XOX+X+X+X+XOX+XOXOX+X+X+XOX+X+X+XOX+X+X+XOX+XOX+XOX+X+X+X+XOXOX+X+X+X+X+X+X+X+XOX+X@X+XOX+X+X+X+X+XOX+XOX+X+XOX+XOX+X+X+X+XOXOX+X}.@X+XOX+X+X+X+X+XOX+X+XOX+X+X+X+XOX+XOX+X+X+X+X+XOXOX+X+X+X+XOX+XOX+X+X+XOXOX+XOXeX+X+X+XOX+XOXOX+XOX+XOX+X+X+XOX+X+XOXOX+X+XOX+X+X+XOX@XOXOX+X+XOX+X+X+XOX+XOX+XOX+XOXOX@XOXOX@X@XOX+X+XOX+XOX+XOXOX+XOX+X+X+X+XOX@XOX+XOX+XOX+X+X+XOXOX+XOX+X+X+X+XOXOX+XOX+X+X+X+XOX+XOXOX+XOX+X+XOX@XOX+X+X+XOXOX+X+X+X+XOX+XOX+X+XOX+XOX@X@XOXOX@X@XOX+X+X+X+XOX+XOX+X+X+X+XOXOX+XOX+X+X+X+XOXOX+X+X+X+XOX+XOX+X+X+XOXOX+X+X+X+XOX+XOX+XOXOX+XOX+XOX+X+X+XOX+X", -"+XOX+XOX@XOXOXOXOXOXOXOXOX+XOXOXOXOX+XOX+XOXOX@X+X+XOXOX+XOXOX+XOXOXOX+XOX+XOX+X+XOX+X+XOXOXOX+X+XOX+XOX+XOXOX+XOX+XOX+X+X+XOXOXOXOXOX+X+XOX+X+X+XOXOX+XOX+X+XOX+XOXOXOXOX+XOX+X+XOX+XOXOXOX+XOXOXOX+XOX+XOX+X+XOXOX+XOX+XOX+X+X+XOX+XOXOX+XOX+X+XOX+XOXOX+XOX+XOXOX+XOXOXOX+X+XOXOX+XOX+XOX+X+X+X+XOXOXOX+XOX+X+XOX+XOXOX+XOX+X+XOXOXOXOX+XOX+XOX+XOX+XOX+X+X}.OX+X+XOXOX+X+XOXOX+X+XOXOXOX+XOX+XOX+X+X+XOXOXOX+XOXOX+XOXOXOX+XOXOXOX+XOX+XOX+X+XOX+XOXOXOXOX+XOXOX+XOX+XOX+X+XOXOXOX+X+XOX+XOXOXOX+XOXOXOX+X+XOXOX+XOX+XOX+X+XOXOXOX+X+X+XOXOX+XOXOXOXOX+X}.@XOXOXOX+XOXOX+XOXOX+XOX+X+XOX+XOX+X+XOX+X+XOX@X+XOXOXOX+XOXOX+XOXOX+X+XOXOXOX+XOX+XOXOXOXOXOXOX+X+XOXOXOXOX+XOX+XOX+XOX+XOX+X+X}.OXOXOX+XOX+X+XOX+XOX+XOXOXOX+XOXOX+XOX+XOX+X+X+XOX+XOX+XOXOXOX+XOXOXOX+XOX+XOX+XOX@XOXOXOX+XOXOXOXOXOX+XOX+X+XOX+XOX+XOXOXOXOX+XOX+XOX+XOX+XOX+X}.+X+XOX+XOXOX+X+XOX+XOX+XOXOX+XOX+XOX+X+X+XOXOX+XOXOX+XOXOXOX+X+XOXOX+XOX+X+XOXOXOX+XOX@XOXOXOXOXOX+XOXOX+XOXOX+X+XOXOXOX+XOX+X+XOX+XOXOX+XOX+X+XOXOXOXOX+XOX+XOX+XOX+XOX+X}.+XOX+XOX+XOX+X+XOX+XOX+XOXOXOX+XOX", -"OXOX+XOXOX@XOX@XOX+X+XOX+XOX+XOXOX+X+XOX+XOXOXOXOXOXOX+XOX+X+XOXOX+XOX+X+XOX+XOXOXOX+XOX+XOXOXOXOX+XOX+X+XOXOXOXOX+XOX+XOX+XOXOX+XOX+XOXOX+XOX+XOXOX+XOXOX+XOX+X+XOX+XOXOXOXOX+XOXOX+X+X+XOXOXOXOXOX+XOXOX+X+XOXOX+X+XOXOX+XOXOXOXOXOX+XOXOX+XOXOXOX+XOXOX+X+XOXOXOX+XOXOX+X+XOX+XOXOX+XOX+X+XOXOXOXOX+XOXOX+XOXOXOXOX+XOX+X+XOXOX+X+XOXOXOX+XOXOX+XOX+XOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOXOXOXOX+XOX+XOXOX+XOXOXOXOX+XOX+X+XOX+XOXOXOX+X+X+XOXOXOXOX+X+XOX+XOXOXOXOX+X+XOX+XOXOX+XOXOX+XOXOX+X+XOXOXOX+XOXOX+X+XOXOX+XOX+XOXOX+XOXOX+XOX+X+XOX+XOXOX+XOX+X+XOX+X+XOX+XOX+XOX+XOXOX+XOXOXOXOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOXOXOXOX+X+X+XOX+XOX+XOX+XOX+X+XOXOXOX+XOX+XOXOX+XOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOXOXOXOX+X+XOX+XOXOX+X+XOXOXOXOX+X+XOXOXOXOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOX+XOX+XOXOX+XOX+X+XOX+XOXOXOXOX+X+XOXOX+XOX+XOX+XeXOX+XOX+XOX+XOXOX+XOX+X+XOXOXOXOX+XOX+XOX+XOXOX+XOXOXOXOX+XOX+XOXOX+XOXOX+XOX+XOXOX+XOXOX@XOX@XOX@XOX@XOXOXOX+XOXOXOX+XOXOX+XOXOXOXOX+XOXOX+XOXOX+X+XOXOXOX+XOX+XOXOX+XOX+XOX+X+XOX+XOXOX+XOX+X+XOX+XOXOXOXOX+X", -"+XOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOX+X+XOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOX+XOXOXOXOXOX+XOXOX+XOXOXOXOXOXOXOXOXOXOXOXOX+XOX+XOXOXOXOX+XOXOX+XOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOX+XOXOX+XOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOX+XOXOXOXOXOX+X+XOXOXOXOXOXOX+XOXOXOXOXOXOXOXOX+X+XOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOX+XOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOXOX+XOXOX+XOXOXOXOX+XOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOX", -"OXOXOX+XOXOXOXOXOX+XOXOX+XOXOX+XOXOX+XOXOX+XOXOX+XOXOXOXOXOX+XOXOX+X+XOXOXOX+XOXOXOX+XOXOXOXOXOXOX+XOXOX+XOXOXOXOX+XOXOX+XOX+XOX+XOXOXOXOX+XOXOXOXOX+XOXOX+XOX+XOXOX+XOXOXOXOX+XOXOX+XOXOXOXOXOXOXOXOX+XOX+XOXOXOXOX+XOXOX+XOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOX+XOXOXOXOX+XOX+XOXOXOXOXOXOXOXOXOXOX+XOXOX+XOXOXOX+XOXOXOX+XOXOX+XOXOXOX+XOXOXOXOX+XOX+XOX+XOXOX+XOXOXOXOX+XOXOXOX+XOXOXOX+XOX+XOXOXOXOXOXOX+XOXOXOX+XOXOXOX+XOXOXOXOX+X+XOXOXOX+XOXOXOX+XOXOXOXOXOXOXOX+XOXOX+XOXOXOX+XOXOXOX+XOXOXOXOXOX+XOXOX+XOXOXOXOXOXOX+XOXOXOX+XOXOXOXOX+XOXOXOX+XOXOXOXOX+XOX+XOXOXOXOXOXOX+XOXOXOX+XOXOXOX+XOXOXOXOX+X+XOXOXOX+XOXOXOXOX+XOXOXOX+XOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOX+XOX+XOXOXOXOX+XOXOXOXOX+XOXOXOX+XOXOXOX+XOX+XOXOXOX+XOXOXOXOX+XOXOXOXOX+X+XOXOXOXOX+X+XOXOXOX+XOXOXOXOX+XOXOXOXOXOXOX+XOXOXOXOX+XOXOX+XOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOX+X+XOXOXOXOX+XOXOX+XOXOXOX+XOXOXOX+XOXOXOX+XOXOXOXOX+XOXOXOXOX+XOXOX+XOXOXOXOXOX+XOXOXOXOXOXOXOX+XOXOXOXOX+XOXOX+XOXOXOX+XOXOXOX+XOXOX+XOXOXOX+XOXOXOXOX+XOX+XOXOXOXOX+XOXOXOXOX+XOXOXOX+XOXOXOX+XOX+XOXOX", -"OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX+XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOX", -"OXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXoXOXOXoXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXoXOXOXoXOXOXOXOXOXoXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXoXOXOXoXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoX@XXX@XXXoXoX@XXXXXoX@X", -"OXOXoXOXOXOXoXOXOXOXoXOXOXOXoXOXoXOXoXOXoXOXoXOXOXoXOXOXOXOXOXOXOXOXOXoXoXOXoXOXOXOXoXOXOXoXOXOXoXOXOXoXOXoXoXOXOXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXoXOXOXoXOXOXoXOXOXOXoXOXoXOXoXOXoXOXOXOXoXOXoXOXOXOXOXoXOXOXOXoXOXOXOXOXoXOXoXOXOXOXoXOXOXOXoXOXOXOXOXOXoXOXoXOXOXoXOXoXOXoXOXoXOXOXOXOXoXOXoXOXOXOXOXoXOXOXoXoXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXoXOXOXoXOXOXoXOXOXoXOXoXoXOXOXoXOXOXoXOXOXoXOXOXoXOXoXOXoXOXoXOXOXOXOXoXOXoXOXOXOXOXoXOXOXOXoXOXOXoXOXOXOXOXoXOXOXOXoXOXoXOXOXoXoXOXoXOXOXOXOXOXOXoXoXOXOXoXOXOXOXOXOXOXoXOXOXoXOXOXOXoXOXOXoXOXOXoXOXOXoXOXOXoXOXoXoXOXOXoXOXOXOXOXOXOXOXOXoXOXOXOXOXOXoXOXOXoXOXOXOXOXoXOXOXoXoXOXOXOXOXOXOXOXoXOXOXoXOXOXoXOXoXOXOXoXOXoXoXOXoXOXoXOXOXoXoXOXOXOXoXOXOXoXOXoXOXoXoXOXOXoXoXOXOXOXoXOXOXoXoXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXoXOXOXoXOXOXoXOXoXoXOXOXoXOXoXoXOXOXoXoXOXOXoXoXOXOXOXOXOXOXOXOXOXOXoXOXoXOXoXOXoXOXOXOXoXOXoXOXOXOXoXOXOXOXoXOXOXOXOXoXOXoXOXOXOXOXOXoXOXOXoXoXOXOXoXoXOXoXOXoXOXOXoXoXOXXX@XoXOXOXOXoXXXoX@XoXXX", -"oXOXOXoXoXOXOXoXoXOXOXoXoXOXOXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXoXoXOXoXOXOXoXoXOXOXoXOXOXOXOXOXOXoXOXOXOXoXOXOXOXOXOXoXOXOXOXOXOXOXXXOXOXOXoXoXOXOXOXOXOXoXOXOXoXOXOXoXOXOXoXOXoXOXOXOXoXOXOXOXOXOXOXOXoXOXOXoXOXOXoXoXOXOXoXOXOXOXOXOXoXOXOXoXOXOXoXoXOXOXOXOXOXOXOXOXoXOXoXOXOXoXOXOXOXoXOXOXOXOXOXOXoXOXOXOXOXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXoXOXoXOXoXOXOXOXOXOXoXOXoXOXOXOXoXOXOXOXOXoXOXoXOXoXOXOXOXOXOXOXoXOXOXOXOXoXoXOXoXOXOXoXOXOXoXOXOXOXoXOXOXOXOXOXOXoXOXOXoXOXOXoXoXOXOXoXOXoXOXOXoXOXOXOXOXOXOXOXOXOXOXoXOXOXoXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXoXOXOXOXoXOXOXoXoXOXoXOXOXoXoXOXOXoXOXOXOXOXOXOXoXOXOXOXoXOXOXoXOXOXOXOXOXOXOXOXoXOXoXOXOXOXOXOXoXOXoXOXoXOXoXOXOXOXOXOXOXoXOXoXOXOXoXOXOXoXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXoXOXoXOXOXOXOXOXOXOXOXOXOXOXOX}.OXOXOXOXOXOXOXOXOXoXOXOXOXOXOXoXOXOXoXoXOXoXOXOXoXOXoXOXoXOXoXOXOXOXOXOXOXoXOXOXoXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXoXOXOXOXoXOXOXOXOXOXOXOXoXOXOXoXOXOXoXoXOXOXoXoXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXOXOXOXOXOXoXOXOXOXOXOXOXoX@XoXoXOXOX@X@XoXoX@X", -"OXoXOXoXOXoXOXOXOXoXOXoXOXoXOXoXoXoXoXOXoXoXoXOXXXOXXXOXOXXXoXOXoXoXoXOXOXOXoXoXOXoXOXOXOXoXoXOXoXOXoXOXoXOXoXoXoXOXoXOXoXoXOXoXoXOXoXoXoXOXXXOXOXXXOXOXoXOXoXOXoXOXoXoXoXoXOXoXOXOXXXOXOXoXoXOXoXOXoXOXoXOXOXoXoXoXOXoXOXoXoXoXOXoXOXoXOXoXOXoXOXXXOXoXOXoXoXoXOXoXOXoXOXoXXXOXoXoXOXoXOXoXOXoXOXoXOXoXOXoXOXOXOXXXOXoXOXoXoXoXOXOXOXoXoXoXOXoXoXOXoXoXoXOXoXoXoXoXOXXXOXoXOXOXOXoXoXoXoXoXOXoXOXOXXXOXOXoXoXoXoXOXoXOXOXoXoXOXoXoXoXOXOXOXoXoXOXoXOXOXOXoXoXOXOXoXOXoXOXoXOXOXOXXXOXoXOXoXoXoXOXoXOXoXOXoXOXoXOXoXoXoXOXoXoXOXoXOXoXoXoXOXoXOXoXOXOXoXoXoXOXoXOXoXoXOXoXoXoXOXoXoXOXoXoXOXoXOXoXoXOXoXOXoXOXOXOXoXoXOXOXOXoXOXOXoXoXoXoXOXOXoXoXoXOXoXOXoXoXOXoXoXOXoXoXoXOXOXOXoXoXoXoXoXOXoXOXoXOXOXOXoXoXoXoXoXOXoXOXoXoXOXOXOXoXOXoXOXoXoXoXOXOXoXoXoXOXoXXXOXoXOXoXOXoXOXXXOXoXoXoXOXoXoXOXOXOXOXoXoXOXoXoXOXoXoXoXOXXXOXXXOXOXXXOXoXOXOXOXoXoXOXoXOXoXOXOXoXoXOXoXoXoXOXOXOXoXOXoXOXoXoXoXOXoXOXoXoXOXoXoXOXoXoXoXOXXXOXoXOXOXoXoXOXOXoXoXoXOXoXOXoXoXoXOXoXOXoXOXoXOXoXOXoXoXOXoXoXoXOXOXOXOXoXoXoXOXoXoXOXoXoXoXOXOXoXoXoXOXoXoXoXXXOXoXOXoXoXXXoXoXXX", -"oXoXOXoXOXoXoXoXoXoXOXoXOXoXoXOXOXoXoXOXoXOXoXoXOXoXoXOXOXOXXXOXoXOXoXoXoXoXoXOXoXOXoXoXoXOXoXoXOXoXoXoXOXoXoXOXOXOXOXOXoXOXoXOXOXoXOXOXOXoXOXoXXXOXOXoXoXoXOXoXoXoXOXoXoXOXoXoXXXOXOXOXOXoXOXoXoXOXoXoXOXoXoXOXoXOXoXOXoXOXoXOXoXoXOXoXOXoXoXOXoXOXXXOXoXOXoXOXoXoXOXoXOXOXXXoXoXOXoXOXOXoXoXOXoXoXoXOXoXOXoXoXXXOXOXXXoXOXoXOXoXOXoXoXoXoXOXoXOXoXoXOXoXOXoXoXOXXXOXoXoXOXOXoXoXoXOXoXoXOXoXoXXXOXOXOXOXoXOXoXoXOXoXoXOXoXoXoXoXOXoXoXoXoXoXOXoXoXOXoXoXOXoXoXoXoXoXOXoXOXoXoXXXOXOXXXoXOXoXOXoXoXOXoXOXoXoXOXXXOXoXOXOXOXoXoXoXoXoXOXoXoXOXoXoXoXOXoXoXOXoXoXoXOXoXoXoXOXoXoXoXOXOXOXoXoXOXoXoXOXoXoXoXOXoXoXOXoXoXoXoXoXoXOXoXOXoXOXoXOXoXoXoXOXOXoXOXXXoXoXoXoXOXoXoXoXOXoXoXoXOXoXoXOXoXoXOXXXOXoXOXoXOXoXoXOXoXoXOXoXoXoXoXoXoXOXoXoXoXOXoXOXoXoXoXoXOXoXOXOXXXOXOXoXOXoXOXoXoXoXOXoXoXOXoXOXoXoXoXoXOXoXOXoXOXOXOXoXOXoXOXoXOXoXoXOXoXoXOXoXoXoXoXOXoXoXoXOXoXoXOXoXoXOXoXoXoXoXOXoXoXOXoXOXoXoXoXoXOXoXOXoXOXOXOXoXOXoXoXOXoXoXOXoXoXOXoXOXoXOXoXOXoXOXoXoXOXoXOXoXoXOXXXOXOXXXOXoXOXoXoXOXoXoXoXoXOXoXOXoXoXOXXXOXOXOXoXoXOXoXoXoXOXoXoXOXoXoXoXoXoXoX", -"oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXXXXXXXoXoXoXXXoXoXXXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXXXXXXXoXoXoXoXoXoXoXoXXXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXXXOXoXOXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXOXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXoXoXXXoXoXoXoXoXoXoXoXoXoXOXXXXXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXOXXXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXXXOXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXOXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXoXoXoXoXoXoXoXoXoXoXOXXXOXOXXXoXoXoXoXoXoXoXoXoXoXoXoXOXoXXXOXXXoXoXoXoXoXoXoXoXoXOXXXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXOXOXXXoXoXoXoXoXoXoXoXoXoXoXoXXXOXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXXXOXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"oXoXoXoXXXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXXXOXXXXXOXXXoXoXoXoXoXoXoXoXoXoXoXXXoXoXXXOXXXoXoXoXoXoXoXoXoXXXXXOXXXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXXXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXXXoXoXoXoXoXoXoXoXXXOXXXXXOXXXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXoXXXoXoXoXoXoXoXoXoXoXoXoXoXoXXXOXXXXXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoX", -"XXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXoXXXoXXXoXXXXXoXXXoXXXoXXXoXoXoXXXoXOXXXXXOXXXOXXXXXXXoXXXXXoXXXoXXXoXXXoXXXXXXXXXoXXXoXXXoXoXXXoXXXoXXXoXXXXXoXXXoXXXoXXXoXoXoXoXoXXXXXXXoXXXoXXXoXXXoXXXoXoXXXXXXXXXXXoXXXXXoXXXoXoXXXoXXXoXXXXXXXXXoXXXoXXXoXXXoXoXXXoXXXXXoXXXXXoXXXoXXXoXXXoXXXoXXXoXoXoXXXXXXXoXXXoXXXXXoXXXoXXXoXXXoXoXOXoXoXXXXXXXoXXXoXXXoXoXoXoXXXoXXXoXXXXXXXXXXXoXoXXXXXXXoXXXoXXXoXXXoXXXoXXXoXoXXXoXXXoXXXXXXXoXoXoXoXXXXXoXXXoXXXXXXXoXXXoXXXoXXXoXXXoXXXoXXXXXoXXXoXXXoXXXoXoXXXXXXXXXoXXXoXXXoXXXoXXXoXXXoXoXXXoXXXoXXXXXXXoXoXXXXXXXXXXXoXoXXXoXXXoXXXoXoXXXoXXXoXXXoXXXoXoXXXoXoXXXoXXXXXoXoXXXXXXXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXXXoXoXoXXXoXXXoXoXXXXXXXoXXXoXOXoXoXoXXXoXXXoXoXoXoXOXXXoXXXXXXXoXXXoXoXoXXXXXoXoXXXXXXXoXXXoXXXXXXXoXXXoXXXoXXXXXoXoXoXXXoXXXoXXXoXXXXXoXXXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXXXoXoXXXoXXXoXXXoXXXoXXXoXXXoXoXoXXXoXXXoXoXXXoXoXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXXXXXoXXXoXoXXXoXoXXXoXoXoXXXoXoXXXoXXXoXXXXXoXXXoXXXoXXXoXoXoXXXoXXXoXXXoXXXoXXXoXXXXXoXXXXXoXXXoXXXoXXXoXoXoXoXXXoXXXoXXX", -"oXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXoXXXoXXXoXXXoXoXXXoXXXoXXXoXXXoXXXoXXXXXXXXXXXXXXXXXXXoXXX}.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.T.oXXXoXoXXXT.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.XXXXoXXXoXXXoXXXoXoXw.w.w.w.5.w.w.w.w.w.w.w.w.w.w.w.w.w.w.5.w.w.w.w.w.w.w.w.w.w.w.w.OXoXoXXXoXXXoXOXXXOXXXoX5.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.5.w.w.w.w.w.}.oXXXXXoXXXoXXXoXoXy.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.}.XXoXXXXXoXXXoXoXy.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.T.oXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXX}.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.E.oXXXoXXXoXXXoXXXXXR.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.}.XXXXoXXXXXXXoXXXoXoXXXoXXXw.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.5.w.w.T.oXoXXXoXXXoXXXoXXXR.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.t.R.oXXXXXoXXXoXXXoXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXoXXXXXXXXXoXoXXXoXXXoXXXoXXXoXoXXXoXXXoXXXoX", -"XXoXoXoXoXoXXXoXoXoXXXoXXXoXXXoXoXoXXXoXXXoXoXXXXXoXXXXXXXoXoXoXoXXXXXoXXXXXXXXXoXXXOXXXXXoXT. h oXoXXXXXoXm XXXXoXoXXXXXoXXXXXoX. X E.XXXXoXXXoXXXXXXXXXXX}. R.XXoXoXXXXXXXoXXXoX* F.oXXXoXXXXXXXXXoXo g XXoXXXoXXXXXoXoXXXoXoXXXoXXXoXXXXXXXoXXXT. 4.XXoXXXXXXXoXoXoXoXW w.oXoXXXXXXXXXoXoXXXoXoXoX|. P oXXXoXXXoXXXXXXXXXI P XXoXoXXXXXoXoXXXXXoXXXXXXXoXoXoXoXXXXXoXXXXXXXXXoXoXXXoXXXXXXXXXXXoXoXoXXXoXXXXXXXoXoXXXXXoXoXXX", -"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT. h XXoXXXoXXXm XXXXXXoXXXXXXXXXXXXX. D.XXXXXXXXXXXXXXXXXXXXF. R.XXXXXXoXXXXXXXXXXX* D.XXXXXXXXXXXXXXXX. g XXXXXXXXXXXXXXXXXXXXXXXXXXoXXXXXXXXXXXXXT. 4.XXXXXXXXXXXXXXXXoXW g XXoXXXXXXXXXXXoXXXXXXXXX}. P XXXXXXXXXXXXXXXXoXW P XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", -"XXXXXXXXXXoXXXXXXXXXXXoXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT. h XXXXXXXXXXm XXXXXXXXXXXXXXXXXXXXo w.XXXXXXXXXXXXXXXXXXXXt. R.XXXXXXXXXXXXXXXXXX* T.XXXXXXXXXXXXXXXXo g oXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT. 4.XXXXXXXXXXXXXXXXXXW . }.XXXXXXXXXXXXXXXXXXXXXX|. P oXXXXXXXXXXXXXXXXXI P XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", -".XXXXXXXXX.XXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXX XXX.XXXXXXXXX.XXXXXXXXX.XXXT. n XXXXXX.XXXm XXXXXXXXX.XXXXXXXXX. I XXXXXXXXXXXXXXXXXXXXW R.XXXXXXXXXX.XXXXXXX* F.XX.XXXXXXXXXXXXXo g XXXX.XXXXXXXXX.XXXXXXXXXXXXXXXXX.XXXXXXXT. 4.XXXXXXXXXXXXXXXXXXW w..XXXXXXXXXXXXXXXXXXX.X}. I oXXXXXXX.XXXXXXXXXE P XXXXXXXXXXXXXXXXXX.XXXXXXXXX.XXXXXXXXXXXXX.X.XXXXXXXXXXX.XXXXXXXXXXXXXXXXXXX.XXX.XXXXXXXXXXXXXXX", -"XXXX.XXXXXXX.XXX.XXX.XXX.XXX.XXX.XXXXX.XXXXX.XXXXX.XXXXXXX.XXXXXXXXX.XXXXXXX.XXXXXXXXXXXXXXXD. h XX.XXXXXXXm XXXXXXXXXXXXXX XXXXX. h XXXX.XXXXXXXXX.XXXXXP R.oXXX.XXX.XXXXXXXXX% D.XXXXXXXX.XXXXXXX. d XXXXXXXXXX.XXXXXXXXX.XXXXXXXXXXX.XXXXXXXT. 4.XX.XXXXXXXXXXXXXXXW h XXXXXXXXXX.XXX.X.X.XXX|. P XXXXXXXXXXXX.XXX.XI . P .XXXXX.XXXXXXX.XXXXXXX.XXX.XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXX.XXX.XXXXX X", -"XX.XXXXX.XXX.XXXXXXXXXXX.XXXXXXX.XXXXXXX.X.XXXXXXX.XXX.XXXXX.XXXXXXXXXXX.XXXXXXXXXXXXX.XXX.XT. h XX.XXXXXXXm XX.X.XXX X.XXXXXXXXX. 1 XX.XXXXXXX.XXX.XXXXX8 R.XXXXXXXXXXXXXX.XXX% D.XXXX.XXX.XXXXXXX. d XXXX.XXXXXXXXX.X.XXXXXXXXX.X.XXXXXXXXXXXT. 4.XXXX.XXX.XXX.X XXXW . |.XX.XXXXXXXXXXXXXXXXX|. I XX.XXXXX.XXXXXXXXXI P XXXXXX.XXX.XXXXXXX.XXXXXXXXX.XXXXXXX.XXX.XXX.XXXXXXXXX.XXX.XXX.XXX.XXXXX.XXXXXXXXX.XXXXXXXXX.XXX", -"XXXXXX.XXX.XXX.XXX.X.XXXXXXXXX.XXX.XXXXXXX.X.XXXXXXXXX.XXXXX.XXXXX.XXXXXXX.XXX.X.XXXXX.XXXXXT. h XXXXXXXX.Xm .XXX.XXXXX.XXXXX.XXX. X.XXXXXXX.XXX.XXXXX, R..XXX.XXX.XXX.XXXXX* D.XX.XXXXX.X.XXX.X. g XX.XXX.XXX.XXXXX.XXXXX.XXX.XXX.X.XXX.XXXT. 4.XXXXXX.XXX.X.XXXXXW t.XXXX.X.XXXXXXXXXXX X|. P XX.XXX.XXXXXXXXX.XI . P XX.XXX.XXX.X.XXXXXXXXX.XXXXX.XXX.XXX.XXX.XXXXX.X.XXX.XXXXX.XXX.X.XXX.XXXXXXX.XXX.XXX.XXX.XXX.XXX", -".X.X.XXXXX.X.XXX.XXXXX.X.X.X.XXXXX.X.X.X.XXXXX.X.X.X.XXX.XXXXX.X.XXX.X.X.XXX.XXX.XXX.XXX.X.XT. h XX.X.X.XXXm X.XXX.XXXXX.X.XXX.X. E.XX.X.X.XXX.XXX.X X R.XX.XXX.XXXXXXX.X X* D..XXX.X.XXXXX.XXX. g XX.X.XXX.XXXXX.XXX.XXX.X.XXX.XXXXX.X.X.XI. 4.XX.X.XXX.XXXXX.X.XW m .X.XXX.X.X X.X.X.X.X|. P XXXX.XXX.X.X.X.XXXI P XX.X.XXX.XXXXX.X.X.X.XXX.XXXXX.XXX.XXXXXXXXX.XXXXX.XXXXX.XXX.XXXXX.XXX.X.XXXXX.XXX.XXX.XXX.XXX.X", -".X.X.XXX.XXX.XXX.X.XXXXX.X.X.XXX.XXX.XXX.X.XXXXXXX.X.XXX.X.XXX.X.XXXXX.XXX.XXX.XXX.XXX.X.XXXI. h .X.X.X.X.Xm .XXX.X.X.X.XXX.X.XXXo u..X.X.X.XXXXX.XXXE. R..XXX.X.X.X.XXX.X.X% D..XXXXX.X.XXXXX.X+ g XXXX.X.X.X.X.X.X.X.X.XXX.XXX.X.XXXXXXXXXI. 4..XXX.X.X.X.XXXXX.XW . |..X.XXX.X.XXX.XXXXX|. P XX.X.X.XXX.XXX.X.XI P .XXX.XXX.X.XXXXX.XXX.XXX.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.XXX.X.X.XXXXX.XXX.X.X", -"XXXX.X.X.XXX.X.XXX.X.X.XXXXX.X.X.XXX.X.XXX.X.X.X.X.X.X XXX.X.XXX.X.X.X.XXX.X.X.XXX.X.X.X.X XI. h .XXXXXXX.Xm X.X.XXXXX.X.X.XXX X. 4..XXXXX.X.X.X.XXXD. R..XXX.X.XXX.X.X.XXX* D.XX.X.XXX.X.X.XXX. g .X.XXX.XXX.XXXXX.X.X.XXX.X.XXX.X.X.X.X.XI. 4..X.X.XXXXX.X.X.X.XW y..XXXXX.X.XXX.X.X.X|. I .X.XXX.XXX.X.XXX.XI P .XXX.X.XXX.X.X.X.X.X.X XXX.X.X.X.XXX.XXX.X.XXX.XXX.X.XXX.X.XXX.XXXXX.X.XXX.X.X.X.X.X.X.X.X.X.XXX", -".X.X.X.XXX.X.X.X.X.XXX.X.X.X.XXX.X.XXX.X.X.X]. X.X.XXX.X.X.X.X.X.XXX.X.X.X.X.XXX.X.X.XXX.X.XI. h .X.X.X.X.Xm X.X.X.X.XXX.XXX.X.X. P .X.X.X.X.X.XXX.Xw. R..X.X.X.XXX.X.X.XXX* D..XXX.X.X.X.XXX.X. g .X.X.XXX.X.X.X.X.XXX.X.XXX.X.XXX.X.XXX.XT. 4.XX.X.X.XXX.X.X.X.XW M .X.X.X.X.XXX.X.XXX`. P .X.XXX.X.XXX.X.X.XI P .X.XXX.X.XXX.X.X.X.X.X.X.X.X.XXX.X.XXX.X.XXX.X.X.X.X.XXX.X.XXX.X.X.XXX.X.X.X.XXX.X.XXX.X.XXX.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X]..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X]..X.XI. h .X.X.X.X.Xm ]..X.X.X.X.X.X]..X.X. d .X.X.X.X.X.X.X.XW R..X.X.X.X.X.X.X.X.X* D..X]..X.X.X.X.X.X. g .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X]..XI. ,..X.X.X.X.X.X.X.X.XW + |..X.X.X.X]..X.X.X|. P ]..X.X.X.X.X.X.XXXI P .X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X.X.X.X.X.X.X.X.X]..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XI. h .X.X.X.X.Xm X.X.X.X.X.X.X.X.X.X. * .X.X.X.X.X.X.X.XZ R..X.X.X.X.X.X.X.X.X* D..X.X.X.X.X.X.X.X. g .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XI. 4..X.X.X.X.X.X.X.X].W u..X.X.X.X.X.X.X.X`. P .X.X.X.X.X.X.X.X.XI . P .X.X.X.X.X.X.X'..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.XXX'..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X XI. h .X.X.X.X.Xm ]..X.X.X.X.X.X.X.X.X. `..X.X.X.X.X.X.X8 R..X.X.X.X.X.X.X.X.X% D..X.X.X.X.X.X.X.X. g .X.X.X.X.X.X.X.X.X.X.X.X.X.X]..X]. X.X.XI. 4..X.X.X.X.X.X.X.X.XW J .X.X.X.X.X.X.X.X|. L .X.X.X.X.X.X.X.X.XI P .X.X.X]..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X'..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X", -".X.X'..X.X.X.X.X.X]..X]..X.X]..X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X]..X.X.X.X.X.X.X.X]..X]..X].I. h .X.X.X.X.Xx ]..X]..X.X].]..X]..X. R.]..X]..X.X]..X, R.]..X.X]..X]..X]..X* D.]..X.X.X.X.X]..X. g ]..X]..X]..X.X.X]..X.X.X.X]..X'..X'..X].I. ,..X.X.X.X.X.X.X.X].W + ]..X]..X.X]..X.X`. P ].]..X]..X]..X]..XI P .X.X.X.X'..X.X.X.X.X]..X.X]..X]..X.X]..X]..X]..X.X.X'..X'..X.X.X.X.X.X.X.X.X.X.X.X.X]..X]..X]..X", -"'..X.X.X'..X.X].]..X.X].]..X.X]..X'.'..X.X'.'..X.X'..X'.].].].]..X].]..X].].].]..X.X]..X]..XI. h .X].]..X].m |.]..X].].]..X.X].].. t..X]..X.X].].|. U.].].]..X.X].]..X].* D.].].]..X.X]..X.X. g .X].]..X.X].]..X.X].].].]..X.X.X.X.X]..XI. ,.]..X].].'..X.X'.].W S.]..X].]..X]. X`. I ]..X]..X.X.X]..X].I P ].'..X.X.X.X.X.X].]..X.X]..X]..X.X'..X.X.X]..X]..X.X.X.X.X.X.X.X'..X'..X'..X'..X]..X.X.X.X]..X].", -".X'.'..X.X'..X'.].].]..X.X.X].]..X.X.X.X.X'..X.X'..X.X.X.X.X]..X].]..X].].].]..X].].|.].].].I. h ]..X].].].m ].].].]..X]..X]..X].. ,.].].].].].].Y. R..X].]..X]..X].].].* D.'.].].].].'..X].. d ].].].].].].].].].]..X'..X.X'..X.X'.].].L. ,.].].].].].]..X'.].W P ].].].].].].].`. P ].].].].].].].].].I P .X.X.X.X'..X'.'.].].].].].].].]..X].].].]. X].]..X'.'..X'..X.X'..X.X.X'..X.X.X'.]..X].].].].].].", -"'..X.X.X'..X'..X]..X].].'..X].].'..X'.'.'..X.X'.'..X'..X'..X].].].].].].].].].].].].].].].].I. h ].].].].].m . |.].].].].].].].]. X. M ].].].]..X].u. R.].].].].].].]. X].% D.]..X].].].].]..X. g .X].].]..X].].].].].'..X.X'..X'..X.X].].I. 4.]..X].].]..X'..X].R * ].].]. X.X]..X`. P ]..X].].].].].].].I . P '..X'.'..X'..X.X.X]..X].].].].].].].].].].].].]..X'..X.X.X'.'..X.X'..X'..X'..X'.].].].]..X].].].", -".X.X.X'..X'..X.X.X'.'..X.X.X'..X.X'.'..X.X'.'..X.X.X'..X].].].].].].].].].].].].].].].].].].E.M M M M M M M M M M M M M M , m M M M M M M M M M M M M M ,.].].].].].m ].].].].].].].].].'.. 8 ].].].].].].5. R.'.].].].].].].].].% * M M M M M M M M M M M M M M M M R.'.].].].].].].].. d ].].].].].].].].].]..X'..X'..X'..X'.].].L. ,.].].].].].].].].].W I.].].].].].].`. P ].].].].].].].]..XI x M M M M M M M M M M M M M M M 5.].].]..X'..X].'.]..X'..X].].].].].].].].].].].].'..X'.'.'..X.X'.'.'..X'.].].].'.].].].].].].].].", -"'.'..X'.'..X'.'.'..X'.'.'.'.'.'.'..X.X'.'..X'..X'.'.'.'.'.].].].].'.].'.].].].].].].].'.].].'.].].].].].].].].'.'.].].].].M `.'.'.].].].'.].].].'.].'.].].].].].].'.x '.].].'.].'.].].].].. + ].].].].].].W L.'.].].].'.].'.].].* 7 ].].].].].].'.].].].].].'.].].].].].].].].].'.].].o d ].].].].].].].].].].'..X'..X.X'.'..X].].I. ,.].].].].'.].].].].R I '.].].].'.].`. L '.].].].].].].].].U E.].].].].].].].'.].].].].'.].]..X'.'..X'.'.'..X.X.X'.'.'.'.].].].'.].].].'.].].]..X'.'..X.X'.'..X'..X'..X'.].].'.'.].].].].].].].", -"'..X'.'.'.'.'.'.'.'.'..X.X'..X'..X'.'.'.'.'.'.'..X'.'..X].'.].].].'.].].'.].].'.].'.'.].'.'.'.].'.].'.'.'.].'.].].'.'.].'.M `.].].].].'.].'.].].].'.].'.].'.].].'.].x '.'.].'.].].'.].'.'.. (.].'.].'.'.M R.'.].'.].].].].'.'.* 7 ].'.'.'.'.].].].'.'.].].].].'.].'.].'.'.'.].].].].. d '.'.].].'.'.'.].'.].'..X'.'.'.'..X'.'.'.L. ,.].].'.].].].'.].].R * '.'.].].'.].`. P ].'.].].'.].].'.].I E.'.].'.].].'.'.].'.'.].'.'.].'.].]..X'.'.'.].'.'.'.].'.].].].].'.].'.].'.'.].'.'.'..X'..X'.'..X'.'.'.'.'.].].'.].].'.].'.'.].].].", -"'.'.'.'..X'.'.'..X'.'.'.'.'.'.'.'.'.'..X'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.].'.'.'.].'.'.'.].].'.'.'.].'.].'.'.'.].'.].'.'.M (.].'.'.'.].'.'.'.'.'.].'.'.'.'.'.'.'.'.x '.].'.'.'.].'.'.].'.. I.'.'.'.'.'.7 L.'.'.'.'.'.'.'.].'.* 7 '.'.'.'.'.'.'.'.'.].'.'.'.'.'.'.'.'.'.].'.'.'.'.'.. g '.].'.'.'.].'.'.'.'.'.'.'.'.'.'.'.'.'.].I. ,.'.'.'.'.'.'.'.'.'.R L.].'.'.].].(. K '.'.'.'.'.'.'.'.'.U E.'.'.'.'.'.].'.'.].'.'.].'.'.'.'.'.'.'..X'.'.'..X'.'.'.'.'.'.'.].'.'.'.].'.'.].'.'.'.'.'.'.'.'.'.'..X'.'.'.'.'.'.].'.'.].'.'.'.'.", -"'.'.'.'.'.'.'..X'.'.'.'.'.'.'.'.'.'.'..X'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.M `.'.'.].'.'.'.'.'.'.'.'.'.'.'.].'.'.'.'.m `.'.'.'.'.'.'.'.'.'.. 5.].].'.'.].% P.'.'.'.'.'.'.'.'.'.% 7 '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.+ d '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.L. ,.'.'.'.'.'.'.'.'.'.R R '.'.].'.'.`. P '.'.'.'.'.'.'.'.].I E.'.'.'.].'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.].'.'.'.'.'.].'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.M ).'.'.'.'.'.'.'.'.].'.'.'.'.'.'.'.'.'.'.x '.'.'.'.'.'.'.'.'.'.. :.'.'.'.'.`.. R.'.'.'.'.'.'.'.'.'.% 7 '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.. d '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.L. ,.'.'.'.'.'.'.'.'.'.R , '.'.'.'.'.`. P '.'.'.'.'.'.'.'.'.L E.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.", -"'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'._.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.M `.'._.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'._.x '.'.'.'.'.'.'.'.'.'.. M '.'.'.'.U. R._.'.'.'.'.'.'.'.'.% 7 '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.. d '.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.L. ,.'.'.'._.'.'.'._.'.R U.'.'.'.'.). K '.'.'.'._._.'.'.'.L W.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'._.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'._.'.'.'.", -"'.'.'._.'.'._.'.'._.'.'.'.'.'._.'.'._.'.'.'._.'.'.'._.'._.'.'.'._.'.'._.'.'.'.'.'.'.'.'.'._.'.'.'.'.'.'.'._.'.'.'.'._.'.'.c ).'.'.'.'.'.'._.'.'.'.'._.'.'.'._.'.'.'.x '.'.'._.'.'.'.'.'.'.. 7 _.'.'.'.y. P.'.'.'._.'.'.'.'.'.+ 7 '.'.'.'.'.'.'._.'.'.'.'.'.'._.'.'.'._.'._.'.'.'.'.. d _.'._.'.'.'._.'.'.'.'.'._.'.'.'.'._._.'.L. ,.'.'.'.'.'.'.'.'.'.R W '.'.'.'.). P '.'._.'.'.'.'.'.'.L Y._.'.'.'._.'.'._.'.'.'.'.'._.'.'.'.'._.'.'.'._.'.'.'.'.'.'.'._.'.'.'.'._._.'.'.'.'.'._.'.'.'._.'._.'.'.'._.'.'._.'.'.'.'.'.'.'.'.", -"'.'.'.'._._.'.'.'.'._._.'.'.'.'._.'.'._.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'.'._.'._.'.'.'._.'.'._.'.'._.'.'.'.M )._.'.'.'.'._.'.'._.'.'.'.'._._.'.'.'.'.z `.'._.'.'._.'._.'.'.. * '.'._.'.<. P._.'.'.'._.'.'.'.'.* 7 '.'.'._._._.'.'.'.'._._.'.'.'._.'.'.'.'.'.'.'.'.'.. d '.'.'.'.'.'.'.'._.'.'.'._.'.'.'.'.'.'.'.S. ,.'._.'.'.'.'.'._.'.R 3 ]._.'.'.). K '.'.'.'.'.'.'.'.'.U E.'.'.'.'.'._.'.'.'.'._.'.'.'._.'.'._.'.'._.'.'.'._.'._.'.'.'.'.'._.'.'.'.'.'.'._._.'.'.'.'.'._.'.'.'.'.'.'._.'.'.'._._.'.'.'._.'.", -"_._.'._.'.'.'._._.'.'.'._.'._.'._.'.'.'.'._._.'._.'._.'.'._.'._._.'._.'._._.'._.'._._.'._.'.'._._._.'.'._.'._.'.'.'.'._._.M ).'.'._.'._._.'.'.'._._.'._.'.'.'._.'._.x _.'.'._.'.'._.'.'.'.. (.'.'.'.T P.'.'._.'._.'._.'._.* 7 _._.'.'.'.'.'._.'._.'.'._.'._.'._.'._.'.'._.'._.'.. d _.'.'._.'._.'._.'._._.'._.'._.'._.'.'._.L. :.'.'.'._._.'._.'._.R U.'._.'.). K _.'._._.'._.'.'.'.L Y.'._._.'._.'.'._._._.'.'._.'._.'.'._.'._.'.'._.'._.'.'.'.'._._.'.'.'._.'._.'._.'.'.'._.'.'._.'.'.'._._.'.'.'.'._.'.'.'.'._.'._.'.", -"'._._.'.'._._.'._.'.'._._.'.'._.'.'._._._._.'.'._.'.'._._.'._.'.'._._.'.'._._.'._._.'.'.'.'._.'.'._._.'.'._._.'.'._._.'.'.c ).'._._.'.'.'.'._._.'._._.'.'._._.'._.'.x `._.'.'._._.'._._._.. P.'._.'.z P.'._._.'.'._.'._.'.* 7 '._._.'.'._._.'._.'.'._._.'.'._.'._._.'._.'._.'.'.. d '._.'._._.'._.'.'._._.'.'._.'._._.'.'._.L. ,.'._._.'._.'.'._.'.R :.'._._.). P _._.'.'._._.'.'._.L Y._._.'.'.'.'._.'.'._._.'._.'.'._.'.'.'.'._.'.'._._.'._._._._.'.'._.'.'._._.'.'._.'._._.'._._._.'._._.'.'._.'.'.'._._.'._._.'.'._.", -"'._.'._._.'._._.'._._.'._._._._._._._.'._.'._._._._._._.'._._._._.'._._.'._.'._._.'._._._._.'._.'._.'._._._.'._._._.'._._.M ~.'._.'._._._._.'._.'._.'._._.'._._.'._.z _._._._.'.'._._.'._.. 7._.'._.7 P._.'._._.'._._.'._.% 7 '._.'._._.'._._.'._._.'._._.'._._.'._._.'._._._._.. d _.'._.'._._.'._._.'._._.'._._.'._._._./.L. :._._.'._._._.'._._.R 7 _._.'.(. K '._._._.'._._.'._.L . Y._.'._._._._.'._._.'._.'._._.'._._._._._._._._.'.'._._.'._.'._._._._._.'._._.'._._._.'._._.'._.'._.'._._._._._._._.'._.'._._.'._.", -"_.'._._._._._._.'._.'._._.'._.'.'._._._._._._._.'._._.'._.'._._._.'._.'._._.'._.'._.'._._._._._._.'._.'._._.'.'._.'._._.'.c )._._._._.'._.'._._._.'._._.'._.'._.'._.x _.'._._._._.'._.'.'.. :.'._.'.+ P._.'._.'._._._._.'.% 7 '._._._._.'.'._.'._.'._._._.'.'._._._.'._._._.'._.. d _._._._._.'._.'._._._._.'._.'._._.'._.'.L. ,._.'.'._.'._._.'._.R Y._.'.). K '._._._.'._.'._._.I Y._.'._.'._.'._.'._.'.'._._._.'._.'._._._.'._._._._.'._.'.'._.'._._._.'._._.'._.'._.'._._._._._._.'._.'._._._._._._.'.'._.'._.'._.", -"_._._.'._._.'._._._._._._._._._._._.'.'._.'._._._._._.'._._.'._._._._._._.'._._._._._._.'.'._._._._._._.'._._._._._.'._._.c )._._.'._._._._._._._._._.'._._._._._._.x _.'._.'._._._._._._.. Z _._.~. , . L._.'._._.'._.'._._.% 7 _._._.'._._._._._._._._._._._._.'._._._.'._._.'._.. d '._._.'._.'._._.'._._._._._._._._.'._._.L. :._._._._._._._.'._.R :.'._.~. K _._._._.'._._._.'.U Y._._._._._._._./._._._._.'._._._._._.'._._._.'._._._._._._._._._.'._._._._._._._._._._.'._._.'._._._._.'._.'._._._._._._._._._._.", -"_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.M ~._._._._._._._._._._._._._._._._._._._.x _._._._._._._._._._.. + 8 _._.U. d P._._._._._._._._._.% 7 _._._._._._._._._._._._._._._._._._._._._._._._.'.. d _._._._._._._._._._._._._._._._._._._._.L. ,._._._._._._._._._.T 7 _._.~. P _._._._._._._._._.L Y._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.", -"_._._._._._._._._._._._./._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._./._.c ~._._._._._._._._._._._._._._._._._._._.z /./._._._._._._._._.. 7 * _._.y. K L._._._._._._._._._.+ 7 _._._._._._._._._._._._._._._._._._._._./._._._._.. s _._._./._._._._./._._._._._._._._._._._.q. :._._._._._._._._./.R . Y._.~. K _._._./._._._._./.L Y._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._./._./._._._._._._./._._._._._._._._._._._._._._._.", -"_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._./._./._._._._._._.l ~._._._._._._._._._._._._._._._._._._._.x _._._._._._._._._._.. c (./.<. :. P._._._._._._._._._.* 7 /._._._./._._./._._._._._._._._._._._._._._._._._.. s _._._._._._._._._./._._._._._._._._._._.L. :._._._._._._._./._.R <._.~. K /._./._._./._._._.L Y._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._./._._._._._._._._._._._./.", -"_._._./._./._._._._._./._./._._._._./._./._._././._./._._._./._._._.^._.^._._./._._./._./._._./._./._._./._._._._._._./._.M (.^._._._._._././._._././._./._._./._._.z _._._./._._./._._./.. J , P._.L + 5. P.^._._._./._./._._.* 7 _./._._._._._._._./._._._._._._._._._.^./._./._._.. s _././._./._._._._._._.^._._./._./._._./.q. :._._./._./._././._.R d _.~. K _._._._._._._././.L Y._./._._._._._./._._._._._././._._._._.^._._._.^._._._._._./._.^./._._./._./._._._._._./._./._._._._._._._._._._._._./._._._._._.", -"_./._._._._._./._._._._._._._._./._._._._._./._._._._._./._._._._./._._._._._._.^._._._./._._._./._._._._._./._._._._._._.c ~._._._._._._._._._./._./._._./._._._._.z /./._._./._._./._._.. J s 6._.z 3 3. P._._./._._._._._./.* , 7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.W._.^._._._._._./._.+ s _._._._._._./._._._._._.^._._./._._._./.L. :./._._./._._._._._.R W.~. P _./._./._./._._._.L <.7.7.7.7.7.7.7.7.7.7.7.7.7.7.P._._.^._._.^._._._._._._./._._._./._._./._._._._._._./._._._._._././._._._._./._._./._._./._._./._.", -"/._./._./././._._././._./././././._./././._./._././././._._././._._.^._.^._./._._._._.^._._.^./._././././._._./._././._./.c ~._.^./._././._././._./._././._./._./._.z /._./._./././._./._.. J K ,./.3 x 7. P././._._./././._./.% k._._./._._.^._./._.. s /._././././._._./._./._._._./._./._./._.j. ;._./._./._._./._./.T 5.~. A /._./._./._._././.U T /._./._.^._._./._./././._./._./._./._./._._._././._._./._./././._._._./._._./././._./._./././._./.", -"^._._._._._.^._.^._._._._._.^._._._./._._./._._./._./._./._./._././././._./._./././._./._./._._._././._./._./._./._./._._.c ~._._./._./._./._._./._._././._./._._./.z /./._./._./._._././.. Z <. J _.+ T 5. P._._./._./._._._./.* P./././._./././._./.. d _._./././._._././._./._./._._./._./././.L. :._./._._._./._./._.T f ~. K _./._._./._./._./.U T /._./._./._./._./._./._._././._././._._././._./._./._./._._././././._./._._._./._._./._._._./._./.", -"_._.^.^.^.^._._._._.^._.^.^._._././././././././._.^._./.^._._.^././././._././././._././././.^._.^._./._././././././././._.M ~./././././._./.^._./././._./././././._.x /././././././././.^.. P 6. s W. 2.5. P./././././././././.* P./././././././././.o s /./././././././._././././././././././._.j. :././././././._././.R . Y. K /././././././._./.L L /././././././._././././././._./._./././._._./././././././././././././././.^._././././.^._.^._._.^.", -"^._._._._.^._.^.^._._.^._.^._.^._.^././._./././.^.^._._._.^.^._././././././././././././._./././././._.^./././././././././.l ~./././././././././././././././././././.z ^././././././././._.. Z U. * k. q.2. P././././././././.^.* k./././././././././.. s /./././././././././././././././././././.S. :./././././././././.Y 2. K /././././././././.L U /./././././././././././././././././././././././././././././././././././././././././._./._._.^././.", -"^.^.^.^._.^._.^.^.^.^.^._.^.^._.^._.^.^.^./.^./.^._.^.^.^._.^.^././././._./././.^./.^./.^./.^./.^.^.^.^._.^./././.^././._.c ~.^././.^./.^./.^./.^.^.^./././././.^./.z /././././././././._.. Z ~.. . 7. Y.3. k././.^./.^././.^./.% P.^././././.^././._.. s /./.^./././././._././.^././././.^././._.j. :.^././././.^./.^._.Y s A ^././././.^././.^.L T ^././././././.^././.^././.^././.^.^.^.^./.^./././././././._./.^./.^././.^./.^./.^.^.^.^.^.^._.^.^.", -"^.^./.^._.^.^.^.^.^.^.^.^.^.^.^.^./.^././.^./.^./.^./.^.^./.^././.^./.^./.^./.^././.^./.^./.^./._./.^././.^./.^.^.^./.^./.l ~.^.^./.^./.^./.^./././.^././.^./.^./.^.z ~./.^./.^.^.^./.^./.. b ^., Z /.5. k./.^././.^././.^./.@ k./.^./.^./.^.^././.. s /././.^./.^./.^./.^.^././.^.^./.^./.^./.q. ;._././.^./.^./.^./.Y . K ^././.^./.^./.^./.L U ^.^.^.^._.^./.^./.^./.^./.^./.^./././.^./.^./.^.^./.^./.^.^./.^././.^./.^././.^./.^././.^.^./.^./.", -"_.^.^./.^.^._.^.^._.^._.^.^._.^./.^././.^./.^./.^./.^./.^././.^.^./.^./.^./.^././.^./././.^././.^.^./.^.^./.^./././.^././.c Q././.^./.^./.^./././.^./.^.^./.^./.^./.z ^.^./.^.^.^./.^./.^.. Z /.d * , ^.3. k.^./.^././.^.^./.^.@ P.^././.^.^././.^./.. s ^./.^./.^./.^./.^././.^./././.^./.^./.^.L. :.^./.^./.^./.^././.Y K ^./.^./.^./.^./.^.L U /./._.^.^./.^./.^./.^./.^./.^./.^./.^./.^./././.^.^././.^./././.^.^./.^././.^././././.^././.^./.^.", -"^.^.^.^._.^.^.^.^.^.^.^./.^.^.^.^.^.^.^.^.^.^./.^.^./.^.^.^.^.^.^.^.^.^.^./.^.^.^.^.^.^.^.^.^.^.^.^.^.^./.^.^.^.^./.^.^.^.c ~.^.^./.^.^.^.^.^.^.^.^.^.^.^.^.^./.^.^.z ^.^.^.^.^.^./.^.^.^.. Z /.K d ^.5. k./.^.^.^.^.^./.^./.% k./.^.^.^./.^.^.^.^.. s ^./.^.^./.^.^.^.^.^.^.^.^.^.^.^.^./.^.^.q. :.^./.^.^.^.^.^.^./.Y A ^.^.^.^./.^.^.^.^.L U ^.^.^.^.^.^.^.^.^./.^.^.^.^.^.^./.^.^.^.^.^.^.^.^./.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.", -"^./.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^./.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^./.c Q.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.z ~.^.^.^.^.^.^.^.^.^.. Z ^.2. Z ^.3. k.^.^.^.^.^.^.^.^.^.@ k.^.^.^.^.^.^.^.^.^.. p ^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.q. ;.^.^.^.^.^.^.^./.^.Y Z ^.^.^.^.^.^.^.^.^.L U ^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^./.^.^.^.^.^.^.^.^./.^.^.^.^.", -"^.^.^.^.!.^.^.!.^.!.^.^.^.^.^.^.!.^.^.^.^.!.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.!.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.l Q.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.j !.^.^.^.^.!.^.^.^.^.. J ^.6. ;.^.3. k.^.^.^.^.^.^.^.^.^.@ k.^.^.^.^.^.^.^.^.^.. s /.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.q. :.!.^.^.^.!.^.^.^.^.Y K ^.^.^.^.^.^.^.^.^.A U ^.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.!.", -"^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.^.^.^.^.^.^.^.!.^.^.!.^.^.^.^.^.!.!.^.^.^.^.^.^.c Q.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.!.^.^.^.j ^.^.^.!.^.^.^.^.^.^.. b ^.U. 6.^.5. . k.^.^.!.^.^.^.!.^.^.+ k.^.^.^.^.^.^.^.!.^.. s ^.^.!.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.^./.j. ;.^.^.^.^.^.^.^.^.^.Y A ^.^.^.^.^.!.^.^.^.L U ^.^.^.^.!.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.!.^.!.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.!.^.^.^.^.^.^.^.^.^.", -"^.!.^.^.^.^.^.^.^.^.^.^.^.^.^.!.^.^.^.!.^.!.!.^.^.!.^.^.^.^.^.^.^.!.^.^.!.^.^.^.!.^.^.^.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.^.^.c Q.^.!.^.!.^.^.^.^.^.^.^.!.^.^.^.^.^.^.^.z ^.^.^.^.^.^.^.^.!.^.. b /.!.. P.^.3. k.^.^.^.!.!.^.^.^.^.% j.^.!.!.^.^.!.^.!.^.. s !.^.^.^.!.^.^.^.!.^.^.!.^.^.!.^.^.^.^.^.q. ;.^.^.^.!.^.^.^.!.^.Y b ^.!.^.!.^.^.^.!.^.U U ^.^.^.^.^.^.^.^.^.!.^.!.^.!.^.^.^.^.^.!.^.^.^.^.^.^.^.!.^.^.^.!.^.^.!.!.^.^.!.^.^.!.^.^.^.^.^.^.^.", -"!.^.^.!.!.!.^.!.!.^.!.^.!.^.!.^.^.!.^.^.!.^.^.^.!.^.^.!.^.!.^.!.^.^.!.!.^.!.!.^.^.!.^.!.^.!.^.!.!.^.!.^.^.!.^.!.!.^.!.^.!.l Q.!.^.^.!.^.!.^.!.!.!.^.^.!.^.!.^.!.!.^.j Q.^.!.!.^.^.!.^.!.^.. b ^.^., Q.^.1. k.^.!.^.^.^.!.^.!.^.% k.^.^.^.!.^.!.^.^.!.o s !.^.^.!.^.^.!.^.^.!.!.^.!.^.!.^.!.^.^.!.q. ;.^.!.^.^.^.!.^.^.!.Y A ^.!.^.^.^.!.!.^.!.A U ^.!.!.^.!.!.^.!.^.^.^.!.^.^.^.!.!.!.^.^.!.!.!.^.!.!.^.^.^.!.^.^.!.!.^.^.^.!.^.!.^.^.!.!.^.!.^.!.!.", -"^.!.^.!.^.!.^.!.!.!.^.!.^.!.^.!.!.!.^.!.^.!.^.!.^.!.^.!.!.!.^.!.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.!.^.!.^.c Q.^.!.^.!.^.!.^.!.^.^.!.!.^.!.!.^.!.!.^.j !.^.!.!.^.!.^.!.!.!.. b ^.!.f + !.^.3. k.^.!.!.!.^.!.!.^.!.@ j.!.!.^.!.!.^.!.^.^.. s ^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.!.^.q. ;.!.^.!.!.!.!.^.!.!.Y A ^.!.^.!.^.!.^.!.^.A U !.^.!.!.^.!.!.!.!.!.^.!.^.!.^.!.^.^.!.!.^.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.", -"!.^.!.^.!.^.!.^.^.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.^.!.^.^.l Q.!.^.!.^.!.!.!.^.!.!.^.!.^.!.^.!.^.^.!.z ^.!.!.^.!.^.!.!.^.^.. b ^.^.U 7 ^.!.3. k.!.^.!.^.!.^.^.!.^.@ k.!.^.!.^.!.^.^.!.!.. p !.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.^.!.q. ;.^.!.!.^.!.^.!.^.^.Y . Z ^.^.!.^.!.^.!.^.!.L U !.!.^.^.^.!.^.^.^.^.!.^.!.^.!.^.!.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.!.^.", -"!.^.!.!.!.^.!.^.!.!.!.^.^.!.!.!.!.^.!.^.!.!.!.^.!.^.!.!.!.^.!.^.^.!.^.!.!.!.^.!.^.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.!.!.!.^.!.l Q.!.!.^.!.^.^.!.^.^.^.!.!.!.!.^.^.!.!.^.j !.^.!.!.^.!.^.^.!.!.. b ^.!.2. l !.!.3. k.!.!.!.^.!.^.!.^.!.@ j.!.^.!.^.^.!.^.!.!.. s ^.!.^.!.!.^.!.^.^.!.!.^.!.^.^.!.^.!.^.!.q. ;.!.^.!.^.!.^.!.^.!.Y z A !.!.!.!.^.!.!.!.!.L U !.^.!.^.!.^.!.^.!.!.^.!.^.!.^.!.^.^.!.!.!.!.^.^.!.^.!.!.^.!.^.^.!.!.^.!.^.^.!.!.^.!.^.^.!.!.^.!.^.", -"!.!.^.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.^.!.!.!.^.^.!.!.!.!.^.^.!.!.^.!.!.!.!.c Q.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.!.!.z !.!.!.!.^.!.!.!.!.!.. b !.!.q. Y !.^.1. l.^.!.!.!.!.!.!.!.^.@ j.!.!.!.!.!.!.!.!.^.. s !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.q. . ;.!.^.!.!.!.!.!.!.!.Y 3. A ^.!.!.!.!.^.^.!.!.A U !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.c Q.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.z !.!.!.!.!.!.!.!.!.!.. b !.!.x. 3.!.!.3. j.!.!.!.!.!.!.!.!.!.@ + f f f f f f f f f f f f f f f x.!.!.!.!.!.!.!.!.!.. s !.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.q. ;.!.!.!.!.!.!.!.!.!.Y x.+ A !.!.!.!.!.!.!.!.!.A s f f f f f f f f f f f f f f 3.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.^.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.!.!.!.!.!.^.!.c Q.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.j !.!.!.!.!.!.!.!.!.!.. b !.!.!.. q.!.!.1. l.!.!.!.!.!.!.!.!.!.@ 4 !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.^.!.. p !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.q. ;.!.!.!.!.!.!.!.!.!.Y x.z A !.!.!.!.!.^.!.!.!.U x.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.l Q.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.j !.!.!.!.!.!.!.!.!.!.. b !.!.!.3 x.!.!.3. j.!.!.!.!.!.!.!.!.!.% 7 !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.. s !.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.q. ;.!.!.!.!.!.!.!.!.!.Y B.3. A !.!.!.!.!.!.!.!.!.A x.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.", -"Z.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.Z.Z.!.!.!.!.l B.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.!.j !.!.!.!.!.!.!.!.!.!.. b !.!.!.j . !.!.!.2. l.!.!.!.!.!.!.!.!.!.% 4 !.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.Z.Z.!.!.!.!.+ p !.Z.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.q. ;.!.!.!.!.Z.!.!.!.!.Y x.B. V !.Z.!.!.!.!.!.!.!.A x.!.!.!.!.Z.!.!.!.Z.!.!.!.A.!.!.A.!.!.Z.!.!.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.!.!.Z.!.!.!.!.!.!.!.!.!.", -"!.!.!.!.Z.!.Z.!.!.!.!.!.Z.!.!.Z.!.!.A.!.!.A.A.!.!.Z.!.Z.!.!.!.!.Z.!.!.!.!.Z.!.Z.!.!.!.Z.Z.!.!.!.!.!.!.A.Z.!.!.A.!.!.!.!.!.l C.Z.!.!.Z.!.!.A.!.!.Z.!.!.!.!.!.Z.!.!.!.j C.!.!.Z.!.!.Z.!.Z.!.. b !.!.!.A , !.Z.!.1. l.!.!.Z.!.Z.!.!.Z.!.@ 7 !.Z.!.Z.Z.!.!.!.!.!.!.Z.!.!.Z.!.A.!.A.!.!.!.!.!.Z.. s !.!.!.!.!.Z.Z.!.!.!.!.!.A.!.!.!.Z.!.Z.!.q. ;.!.Z.!.!.!.Z.!.!.!.F x.Z.5 A !.!.!.!.Z.!.Z.!.!.A . x.!.Z.!.!.!.!.A.!.!.!.!.Z.!.!.!.!.!.!.!.Z.!.Z.!.!.!.!.Z.!.!.!.!.!.Z.!.!.!.!.!.Z.!.!.!.!.!.Z.!.!.!.Z.!.!.Z.!.!.!.!.!.Z.Z.!.!.Z.!.!.", -"!.Z.Z.!.Z.!.!.!.Z.!.Z.Z.!.Z.!.!.Z.!.Z.!.Z.!.A.!.!.!.!.Z.!.Z.Z.!.!.Z.Z.!.Z.!.!.Z.Z.Z.!.!.!.Z.!.Z.Z.!.Z.!.!.!.Z.!.!.Z.Z.!.!.l Q.!.Z.!.Z.!.A.!.Z.!.!.!.Z.Z.Z.!.Z.!.Z.!.j !.Z.Z.!.!.Z.!.!.Z.Z.. b !.Z.!.1. f !.!.!.1. q.Z.!.Z.!.!.!.Z.!.!.% 5 Z.!.!.Z.!.!.Z.Z.Z.!.Z.!.!.Z.!.Z.Z.!.Z.!.!.Z.Z.!.!.. p !.Z.Z.Z.!.!.!.Z.!.Z.!.!.Z.!.Z.!.Z.!.!.Z.q. ;.Z.!.!.Z.!.Z.!.Z.!.Y x.!.;. b !.!.Z.Z.!.!.Z.!.Z.A x.Z.!.!.Z.Z.!.Z.!.!.Z.Z.!.Z.!.Z.!.!.Z.Z.!.!.Z.!.Z.Z.!.Z.!.Z.!.Z.!.!.!.Z.Z.Z.!.Z.!.Z.!.Z.!.!.!.Z.Z.Z.!.!.Z.!.Z.Z.!.!.!.!.!.Z.!.!.Z.", -"Z.!.!.!.!.Z.!.Z.!.Z.Z.!.Z.!.Z.!.!.A.!.Z.!.Z.!.Z.Z.!.Z.!.!.!.!.Z.!.!.!.Z.!.!.Z.!.!.Z.Z.!.Z.!.Z.!.!.Z.!.!.Z.!.A.A.Z.!.!.!.Z.l C.Z.!.Z.!.Z.!.Z.!.A.Z.!.!.!.!.Z.!.Z.!.Z.j Z.!.!.!.Z.!.Z.!.!.!.. b !.Z.!.0. A Z.!.Z.1. l.Z.!.!.Z.!.Z.!.Z.!.% 4 !.!.Z.!.!.Z.!.!.Z.!.!.!.Z.!.Z.!.!.!.!.Z.Z.!.!.!.!.. p !.!.!.Z.Z.!.Z.!.Z.!.!.Z.!.Z.!.Z.!.Z.Z.!.q. %.!.!.!.Z.!.!.Z.!.Z.F x.!.l. V !.Z.!.!.Z.!.!.Z.!.A z.!.!.Z.!.Z.!.Z.!.Z.!.!.!.!.Z.A.A.Z.!.!.!.!.!.!.Z.!.Z.!.Z.!.Z.!.A.Z.!.!.!.!.Z.!.Z.!.Z.!.A.Z.!.A.!.!.Z.!.!.Z.!.Z.!.Z.!.!.Z.!.!.!.Z.", -"!.Z.Z.Z.Z.!.Z.!.Z.!.!.Z.!.Z.!.Z.Z.!.Z.!.Z.!.Z.!.Z.!.!.Z.Z.Z.Z.!.Z.Z.Z.!.Z.!.!.Z.Z.!.!.Z.!.Z.!.Z.A.A.Z.Z.!.Z.A.A.!.Z.Z.Z.!.l Q.!.Z.!.Z.!.A.A.Z.A.!.Z.Z.!.Z.!.Z.!.Z.!.z !.Z.Z.!.Z.Z.!.Z.!.Z.. b Z.!.!.x. ;.Z.!.!.1. q.!.Z.Z.!.Z.!.Z.!.Z.% 4 Z.!.Z.!.Z.!.Z.Z.!.!.Z.Z.!.Z.!.A.A.Z.A.!.!.Z.Z.Z.Z.. s !.Z.Z.!.!.Z.!.Z.!.Z.Z.!.Z.!.Z.!.Z.!.!.Z.q. ;.Z.Z.Z.!.Z.Z.!.!.Z.Y z.Z.!.% V !.!.Z.Z.!.Z.!.!.Z.A x.Z.Z.!.Z.!.Z.!.Z.!.Z.!.Z.A.A.A.A.!.Z.!.Z.Z.!.Z.!.Z.!.Z.!.A.A.Z.A.!.Z.Z.!.Z.!.Z.!.A.A.Z.A.!.Z.!.Z.Z.!.Z.!.!.Z.!.Z.!.Z.Z.!.Z.Z.Z.!.", -"Z.Z.Z.!.!.Z.!.Z.Z.!.Z.!.Z.!.Z.!.A.Z.A.A.Z.A.Z.A.Z.!.Z.!.Z.Z.Z.Z.!.Z.Z.Z.Z.!.!.Z.!.Z.Z.!.Z.Z.Z.!.Z.A.Z.A.Z.A.Z.!.Z.!.Z.!.!.l C.!.A.A.Z.A.Z.A.Z.A.Z.!.Z.!.!.Z.Z.Z.Z.Z.j Z.Z.!.Z.!.Z.!.Z.!.Z.. b !.Z.!.Z.+ 6.Z.!.!.1. q.!.Z.!.Z.A.Z.Z.Z.Z.+ 4 Z.A.A.Z.Z.Z.Z.!.!.Z.Z.Z.!.Z.!.Z.A.Z.A.Z.Z.Z.Z.!.Z.+ s Z.!.Z.Z.!.Z.Z.Z.!.Z.!.!.Z.Z.Z.!.Z.Z.Z.!.q. ;.Z.!.Z.Z.Z.A.Z.A.A.F z.!.!.A V Z.A.A.Z.!.!.Z.Z.!.D x.Z.!.Z.!.Z.!.Z.Z.A.Z.A.A.Z.A.Z.A.Z.Z.!.Z.!.Z.!.Z.Z.A.Z.A.Z.!.Z.!.Z.!.Z.!.!.Z.Z.Z.!.Z.!.Z.Z.A.Z.!.!.Z.!.Z.Z.!.Z.!.Z.Z.!.Z.Z.Z.!.Z.", -"Z.!.Z.Z.Z.Z.Z.!.Z.Z.Z.!.Z.Z.Z.Z.Z.A.A.Z.A.Z.A.A.Z.Z.Z.Z.!.!.Z.!.Z.!.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.A.A.A.Z.Z.A.A.Z.Z.Z.Z.Z.Z.l C.Z.A.A.A.Z.A.Z.A.Z.Z.Z.Z.Z.Z.Z.Z.!.!.Z.j Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.. b Z.Z.Z.V.3 l.Z.Z.Z.1. l.Z.A.Z.A.Z.A.!.!.Z.* 4 A.A.Z.A.Z.!.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.A.Z.Z.A.!.!.Z.Z.Z.. p Z.Z.!.Z.Z.Z.!.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.!.Z.Z.0. %.Z.Z.!.Z.A.Z.A.Z.A.F z.Z.Z.6. A A.Z.Z.Z.Z.Z.Z.Z.Z.A z.Z.Z.Z.!.Z.Z.Z.!.Z.A.A.Z.A.Z.A.Z.!.Z.Z.Z.Z.Z.Z.Z.A.A.A.Z.Z.Z.A.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.A.A.A.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.!.Z.Z.Z.", -"!.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.Z.A.Z.A.Z.Z.A.A.Z.Z.!.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.!.A.Z.Z.A.A.Z.A.A.!.Z.!.Z.Z.l C.Z.Z.A.A.A.A.Z.A.A.Z.Z.Z.Z.Z.!.Z.Z.Z.!.j Z.Z.Z.Z.!.Z.!.!.Z.Z.. b Z.!.Z.!.j C.!.Z.Z.1. 0.A.Z.Z.A.Z.Z.Z.Z.Z.% 5 Z.A.A.Z.Z.Z.Z.!.!.Z.Z.Z.!.Z.!.Z.A.A.Z.A.Z.Z.Z.Z.Z.. p !.Z.!.Z.!.Z.!.Z.Z.Z.Z.!.Z.Z.Z.!.Z.Z.Z.Z.q. ;.Z.!.Z.Z.A.A.Z.A.A.F x.Z.Z.C.. V Z.Z.A.Z.!.!.Z.!.Z.A x.Z.!.Z.Z.Z.!.Z.Z.A.Z.A.A.Z.A.A.A.Z.Z.Z.Z.!.Z.!.Z.A.Z.A.Z.A.A.Z.A.Z.Z.Z.Z.Z.!.Z.Z.!.Z.!.Z.A.Z.A.Z.Z.Z.Z.!.Z.!.Z.Z.Z.Z.Z.Z.!.Z.!.Z.", -"Z.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.!.Z.Z.Z.!.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.l B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.j Z.Z.!.Z.Z.Z.Z.Z.Z.Z.. b Z.V.Z.Z.F % Z.Z.Z.Z.1. l.Z.Z.Z.Z.Z.Z.Z.Z.Z.@ 4 Z.Z.Z.Z.Z.Z.!.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.. s Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.q. ;.Z.Z.Z.Z.Z.Z.Z.Z.Z.F z.Z.!.Z.j A Z.Z.Z.!.V.Z.Z.Z.Z.A z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.!.V.Z.Z.Z.", -"Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.k B.Z.Z.Z.Z.Z.Z.A.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.j Z.Z.Z.Z.Z.Z.Z.Z.Z.Z. l Z.Z.Z.Z.1. 5 Z.Z.Z.Z.1. 0.A.Z.Z.Z.Z.Z.Z.Z.Z.@ 4 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.. p !.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.q. %.Z.Z.Z.Z.Z.Z.Z.Z.Z.F z.Z.Z.Z.1. V A.Z.Z.V.Z.Z.Z.Z.Z.A z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.", -"Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.C.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.C.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.l C.Z.Z.Z.Z.V.Z.V.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.V.j Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.. b Z.Z.Z.Z.q. l Z.Z.V.Z.1. q.Z.Z.Z.Z.Z.Z.Z.Z.Z.@ 4 Z.Z.Z.C.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.V.Z.. p V.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.q. ;.Z.Z.V.Z.Z.Z.C.Z.Z.F z.Z.Z.Z.M. V Z.Z.Z.Z.Z.V.Z.V.Z.A z.Z.Z.Z.Z.Z.Z.Z.Z.Z.A.V.A.Z.Z.Z.Z.Z.V.Z.Z.V.Z.Z.Z.Z.V.Z.Z.V.Z.Z.C.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.", -"Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.V.Z.Z.Z.Z.Z.l C.Z.Z.Z.Z.Z.Z.V.Z.C.V.Z.V.Z.Z.Z.Z.Z.Z.Z.j V.V.Z.Z.Z.Z.V.V.Z.Z.. b Z.Z.Z.Z.M. #.Z.Z.Z.Z.1. 0.Z.Z.Z.Z.Z.Z.V.Z.Z.@ 4 Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.V.. p Z.Z.Z.Z.Z.Z.Z.Z.V.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.0. %.Z.Z.Z.Z.Z.Z.Z.Z.Z.D z.V.Z.V.Z.4 V Z.Z.Z.Z.Z.Z.Z.Z.Z.A z.Z.V.Z.V.V.Z.Z.V.A.V.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.V.Z.Z.Z.Z.Z.V.Z.Z.Z.V.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.", -"V.Z.Z.V.V.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.V.Z.V.Z.Z.V.Z.V.Z.Z.Z.Z.V.Z.V.Z.Z.V.Z.V.Z.V.Z.Z.Z.Z.V.Z.Z.V.Z.Z.V.Z.V.Z.V.Z.Z.Z.Z.V.Z.Z.Z.Z.l N.Z.V.Z.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.V.j C.Z.Z.V.Z.Z.Z.Z.Z.Z.. b V.Z.V.Z.Z.+ 1.Z.V.Z.V.1. l.Z.V.V.Z.V.Z.Z.Z.Z.@ 5 V.Z.Z.V.Z.Z.V.Z.Z.V.Z.V.Z.V.Z.V.Z.Z.V.Z.Z.Z.V.Z.Z.. p Z.Z.V.Z.V.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.V.Z.V.Z.9. %.Z.V.Z.Z.Z.V.Z.Z.Z.F z.Z.Z.Z.Z.F V V.Z.Z.Z.Z.V.Z.Z.V.A z.Z.Z.Z.Z.Z.Z.Z.Z.V.A.V.Z.V.C.Z.Z.V.Z.Z.Z.V.Z.Z.V.Z.Z.V.Z.V.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.V.Z.Z.V.Z.Z.Z.Z.Z.Z.V.Z.Z.Z.Z.V.Z.Z.V.Z.V.Z.V.Z.Z.", -"Z.V.V.Z.V.Z.V.Z.Z.Z.V.V.Z.Z.Z.V.Z.V.V.Z.Z.Z.Z.V.Z.Z.V.Z.V.Z.Z.V.Z.V.V.Z.Z.Z.Z.V.Z.Z.V.Z.Z.Z.Z.Z.V.Z.Z.V.Z.Z.Z.V.Z.V.Z.V.Z.l N.Z.Z.V.Z.Z.Z.V.Z.Z.V.Z.V.Z.Z.Z.Z.V.V.Z.a Z.V.Z.V.Z.Z.Z.Z.V.V.. v Z.Z.Z.V.Z.< 0.Z.Z.V.Z.>. 0.Z.V.Z.V.V.Z.V.Z.Z.@ 4 V.Z.Z.Z.Z.V.Z.V.V.Z.Z.V.Z.V.Z.V.V.Z.Z.V.V.V.Z.Z.Z.. p Z.V.V.Z.V.Z.Z.Z.Z.Z.Z.V.Z.V.V.Z.V.Z.V.Z.q. %.Z.Z.V.Z.Z.Z.V.Z.Z.F z.Z.V.Z.Z.0. b V.Z.V.V.Z.Z.V.Z.Z.A z.V.Z.V.Z.V.Z.Z.Z.Z.V.V.Z.V.Z.V.Z.V.Z.V.Z.Z.V.Z.Z.V.V.Z.Z.Z.V.Z.Z.V.Z.V.Z.V.V.V.Z.V.Z.V.Z.Z.V.Z.V.V.Z.V.Z.Z.V.Z.V.Z.V.V.Z.Z.Z.Z.V.", -"V.Z.Z.V.Z.V.Z.V.V.Z.V.Z.V.Z.V.Z.V.Z.Z.V.V.V.Z.V.V.V.Z.V.V.Z.V.Z.V.Z.Z.V.V.V.Z.V.V.V.Z.V.Z.V.V.Z.V.V.V.Z.V.V.V.Z.V.Z.V.Z.Z.k C.V.V.Z.V.V.V.Z.V.V.Z.V.Z.V.V.V.V.Z.Z.V.j V.Z.V.Z.V.V.V.Z.V.V.. b V.V.V.Z.V.k z.V.V.Z.V.1. . 0.V.Z.Z.Z.Z.V.Z.V.V.@ 5 Z.V.V.Z.V.Z.V.Z.V.Z.V.Z.V.Z.V.Z.Z.V.Z.Z.V.Z.V.Z.V.o p V.Z.Z.V.Z.V.V.V.V.V.V.Z.V.Z.V.Z.V.Z.V.C.0. %.C.V.Z.V.V.Z.V.Z.V.F z.V.V.V.Z.V.% b Z.V.Z.V.V.V.Z.V.V.A h.V.Z.V.V.Z.V.V.V.Z.V.Z.V.Z.V.Z.V.Z.V.Z.V.V.Z.V.Z.V.Z.V.V.V.Z.V.V.Z.V.Z.V.Z.C.Z.V.Z.V.Z.V.V.Z.V.Z.V.Z.V.V.V.Z.V.Z.V.Z.Z.V.V.V.Z.V.", -"V.V.Z.Z.V.Z.V.V.Z.V.Z.V.Z.Z.V.V.Z.Z.V.Z.V.Z.V.Z.V.Z.V.Z.Z.Z.V.V.Z.Z.V.Z.V.Z.V.Z.V.Z.V.Z.V.Z.V.V.Z.Z.V.V.Z.V.V.Z.Z.V.Z.V.V.l N.Z.Z.V.Z.V.Z.V.V.Z.V.Z.V.Z.V.Z.Z.V.V.Z.j Z.C.V.Z.Z.V.Z.V.Z.Z.. v Z.V.Z.Z.V.F . Z.V.Z.Z.Z.>. q.Z.V.V.Z.Z.Z.V.V.Z.@ 4 V.V.Z.V.V.Z.Z.V.Z.V.Z.V.Z.V.Z.V.V.V.Z.V.V.V.V.Z.V.. p Z.V.V.V.V.Z.V.Z.Z.V.Z.V.Z.V.Z.V.Z.V.Z.V.9. %.V.Z.V.V.Z.V.Z.V.Z.F z.V.Z.V.V.Z.b A Z.V.V.Z.Z.V.V.Z.V.C z.V.Z.Z.V.V.Z.Z.V.V.V.Z.Z.V.Z.V.V.V.Z.V.Z.Z.Z.V.V.Z.V.Z.V.Z.V.V.Z.V.Z.V.Z.V.Z.Z.Z.V.V.Z.Z.Z.Z.Z.V.V.Z.Z.V.Z.V.Z.V.Z.Z.V.Z.Z.V.Z.V.", -"V.Z.V.V.V.V.V.Z.V.V.V.V.V.V.V.Z.V.V.V.V.V.V.V.V.Z.V.V.V.V.V.V.Z.V.V.V.V.V.V.V.V.Z.V.V.V.V.V.Z.V.V.V.V.Z.V.Z.V.V.V.V.V.Z.V.l N.V.V.V.Z.V.V.V.Z.V.V.V.V.Z.V.V.V.V.V.V.a V.V.V.V.V.V.V.V.V.V.. v V.Z.V.V.V.1. 3 V.V.V.V.V.>. 0.V.V.V.V.V.V.V.Z.V.@ 5 V.Z.V.V.V.V.V.V.Z.V.V.V.Z.V.V.V.V.Z.V.V.Z.Z.V.V.V.. p V.Z.V.Z.Z.V.V.V.V.Z.V.V.V.V.Z.V.V.V.Z.V.0. %.V.V.V.Z.V.V.V.V.V.F z.V.Z.V.Z.V.6. v V.V.Z.Z.V.V.Z.V.V.A z.V.V.Z.V.Z.V.V.Z.V.Z.V.V.V.V.V.Z.Z.V.V.V.V.V.V.Z.V.V.Z.V.V.V.Z.V.V.V.V.Z.V.V.V.V.V.Z.V.V.V.V.V.Z.V.V.Z.V.V.V.V.Z.V.V.V.V.V.Z.V.V.", -"V.V.Z.V.Z.V.V.Z.V.Z.V.Z.Z.V.V.V.Z.V.Z.V.Z.V.Z.V.Z.V.V.Z.V.V.V.V.Z.V.V.Z.Z.V.Z.V.Z.V.V.Z.C.V.V.V.V.Z.V.Z.V.Z.V.V.V.Z.V.V.V.l N.V.V.V.V.Z.V.V.Z.V.V.Z.V.V.V.Z.V.Z.V.Z.j C.V.Z.C.V.Z.V.Z.V.V.o l Z.V.Z.V.Z.0. f V.V.V.V.V.>. . 0.V.Z.V.V.V.V.V.V.V.+ 5 V.Z.V.V.Z.V.Z.V.V.V.Z.Z.V.Z.V.V.V.V.V.Z.V.V.V.V.Z.. p V.V.V.Z.V.Z.V.V.Z.V.Z.V.V.Z.V.Z.C.Z.V.V.q. #.Z.V.V.Z.V.V.V.Z.V.F z.V.V.V.V.V.N.. V V.V.V.V.V.V.V.V.V.A z.V.Z.V.V.Z.V.V.V.V.Z.V.V.Z.V.Z.V.Z.V.V.Z.C.V.V.V.V.Z.V.Z.V.V.V.V.V.Z.V.V.V.V.V.Z.V.Z.V.V.V.V.V.V.V.Z.V.Z.V.V.V.V.Z.V.V.Z.V.Z.V.V.", -"V.V.V.V.V.V.V.V.V.V.V.V.V.C.V.V.V.V.V.V.V.V.V.V.V.C.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.k N.V.Z.V.V.V.V.V.V.V.V.V.Z.V.V.V.V.V.V.V.a V.V.V.V.V.V.V.V.V.V.. v V.V.V.V.V.v. C V.V.V.V.V.>. . 0.V.V.V.V.V.V.V.V.V.@ * %.%.%.%.&.%.%.%.%.%.%.%.&.%.%.%.%.>.V.V.V.V.Z.V.V.. , %.%.&.%.%.%.%.%.%.%.%.%.%.%.-.V.V.V.V.V.0. %.V.V.V.V.V.V.V.V.V.F z.V.V.V.V.V.V.f b V.V.V.V.V.V.V.V.V.A #.%.%.%.%.%.%.%.%.%.%.%.%.%.&.%.%.%.z.V.V.V.V.V.V.V.V.V.V.V.V.Z.V.V.V.V.V.Z.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.Z.V.V.V.V.V.V.V.V.", -"V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.l N.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.j V.V.V.V.V.V.V.V.V.V.. v V.V.V.V.V.V.+ &.V.V.V.V.V.>. 0.V.V.V.V.V.V.V.V.V.@ @ V.V.V.V.V.V.V.. i V.V.V.V.V.9. %.V.V.V.V.V.V.V.V.V.F h.V.V.V.V.V.V.&. v V.V.V.V.V.V.V.V.V.C 0.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.", -"V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.l v.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.j V.V.V.V.V.V.V.V.V.V.. v V.V.V.V.V.V.4 6.V.V.V.V.V.>. 0.V.V.V.V.V.V.V.V.V.@ @ V.V.V.V.V.V.V.. i V.V.V.V.V.0. %.V.V.V.V.V.V.V.V.V.F z.V.V.V.V.V.V.h. C V.V.V.V.V.V.V.V.V.A 9.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.", -"V.V.V.V.V.V.V.V.V.V.V.V.m.V.V.V.V.V.m.V.V.V.V.V.V.m.V.V.V.m.V.V.V.V.m.V.V.V.V.V.V.V.V.V.V.m.V.V.V.V.V.V.V.V.V.m.V.m.V.V.V.k v.V.V.V.V.V.m.V.V.m.V.V.V.V.V.V.V.V.V.V.a V.V.V.V.m.V.V.V.V.V.. v m.V.V.m.V.V.l . 0.V.V.V.V.V.>. 0.V.V.V.V.V.V.V.V.V.@ % V.V.m.V.V.V.V.. i V.V.V.V.V.9. %.V.V.m.V.V.V.m.V.V.D h.V.V.V.V.V.V.V.< C V.V.V.V.V.V.V.V.V.C 9.Z.V.V.V.V.V.V.V.m.V.V.V.m.V.V.V.V.V.V.V.V.V.C.V.V.V.m.V.V.V.V.V.V.V.V.V.V.V.V.V.V.m.V.V.m.V.", -"V.V.m.V.V.V.m.V.V.m.V.V.V.V.V.m.V.V.V.V.m.V.V.m.V.V.V.V.V.V.V.V.V.V.V.V.m.V.V.m.V.V.V.m.V.V.V.V.V.V.V.m.m.V.V.V.V.V.V.V.V.k v.V.V.V.m.V.V.V.V.V.m.V.V.m.V.m.V.V.V.m.f V.V.m.V.V.V.m.V.V.V.. v V.m.V.V.V.V.#. m.m.V.V.V.V.>. 0.V.V.m.V.V.V.V.V.V.@ % V.V.V.V.V.V.V.. i V.V.V.V.V.0. %.V.V.V.V.V.V.V.V.V.D z.V.V.V.V.V.V.V.D v V.V.V.V.V.V.V.V.V.C 9.V.V.V.m.V.V.m.V.V.V.m.V.V.V.V.V.V.V.m.V.m.V.m.V.V.V.V.V.V.V.V.V.m.V.V.m.V.V.V.V.V.V.V.V.V.V.", -"V.m.V.V.V.m.V.m.V.m.m.V.m.V.V.m.m.V.m.V.V.V.m.V.m.V.m.V.m.V.V.V.m.V.m.V.V.V.m.V.V.m.m.V.m.V.m.V.m.V.m.V.m.V.V.V.V.V.m.V.V.k v.V.m.V.m.V.m.V.V.V.V.V.V.V.m.V.m.V.V.V.f N.V.m.V.V.m.V.V.m.V.. v V.V.V.V.V.V.=. * V.m.V.V.V.V.*. . 0.m.V.m.V.V.V.m.V.V.@ % V.m.V.m.V.m.m.. i V.m.m.m.V.9. #.V.m.m.V.m.V.V.V.V.D h.V.m.V.m.m.m.V.9. v V.V.m.m.V.V.m.V.m.A 9.V.V.V.V.m.m.V.V.m.V.V.m.m.V.V.V.m.m.V.V.V.m.m.V.V.m.m.V.V.m.m.V.m.V.m.V.m.V.V.V.m.m.V.m.m.V.", -"V.V.V.m.V.m.V.V.m.V.V.m.V.V.m.V.V.V.m.V.m.V.V.V.V.m.V.m.V.V.m.m.V.V.m.V.m.V.V.V.m.V.m.V.V.m.V.V.V.V.m.V.V.V.m.m.m.m.V.m.V.l v.V.V.m.V.V.m.V.m.V.V.m.m.V.V.m.V.m.m.V.a m.m.V.V.m.V.m.V.m.m.. v m.V.m.m.V.m.0. i V.V.m.m.m.V.*. 0.m.V.V.V.m.m.V.V.m.@ % m.V.V.V.V.m.V.. i V.V.V.V.m.9. %.m.V.V.m.V.V.m.m.m.D h.m.V.m.V.V.V.V.V.@ C m.V.V.V.m.V.V.V.V.C 9.m.m.m.V.V.V.V.m.V.V.m.V.V.V.m.V.V.V.m.m.V.V.V.V.m.V.V.m.m.V.V.m.V.V.m.V.V.V.V.m.V.V.V.V.V.m.", -"m.m.m.V.m.V.m.V.V.m.V.V.m.V.V.m.m.V.V.m.V.m.V.m.V.m.V.m.V.V.m.V.m.V.V.m.V.m.V.m.V.V.m.V.m.V.V.m.m.V.V.m.V.m.V.V.V.m.V.m.V.k v.V.V.V.m.V.V.m.V.m.m.V.m.V.V.V.m.V.m.V.a V.V.m.m.V.V.V.m.V.m.. v V.m.V.V.V.V.v. v V.m.V.V.m.m.*. 0.V.m.V.m.V.V.m.V.V.@ @ m.V.m.m.V.m.V.. p V.V.V.m.V.9. %.V.V.V.m.m.V.m.V.V.D h.V.m.V.m.V.m.V.m.l v V.m.V.V.m.V.m.V.V.C 9.V.V.V.m.V.m.m.V.m.V.V.m.V.V.m.V.m.V.V.V.V.m.m.V.m.V.V.m.V.m.m.V.m.V.V.V.m.m.m.V.V.V.m.m.V.V.", -"m.V.V.m.V.m.V.m.m.V.m.m.m.m.m.V.V.m.V.m.V.m.m.V.V.m.m.V.m.m.V.m.V.m.V.m.V.m.m.V.m.m.V.m.V.m.m.V.V.m.m.V.m.V.m.V.m.V.m.V.m.k v.V.m.m.V.m.m.V.m.V.m.V.m.m.m.m.m.m.V.m.a m.m.V.m.V.m.m.V.m.V.. k V.V.m.m.m.m.m.@ #.m.V.m.m.V.V.*. 0.m.V.m.V.m.V.m.m.m.@ @ V.m.m.V.m.V.m.+ i m.m.m.m.V.9. #.m.m.V.m.V.m.V.m.m.D h.V.m.V.m.V.V.m.V.-. v m.V.m.V.m.m.V.m.m.C 9.V.m.m.V.m.V.V.m.V.m.m.V.m.m.V.m.V.m.m.m.V.m.V.m.V.m.m.V.m.V.V.m.m.m.m.m.m.V.V.m.m.m.m.V.m.m.", -"m.m.V.V.m.V.m.m.m.m.V.V.V.V.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.V.V.m.V.m.m.m.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.V.k v.m.V.m.m.m.m.m.V.m.V.m.m.V.m.V.V.m.m.V.a N.m.V.m.m.V.m.m.m.m.. v m.V.m.m.m.V.m.5 =.V.V.m.m.m.m.*. 0.m.m.m.m.m.m.V.V.m.@ % m.V.m.m.m.V.m.. i m.V.m.V.m.0. %.m.V.m.m.m.V.m.m.m.D h.m.V.m.m.m.m.V.m.c. v V.m.V.m.m.m.m.m.m.C 9.m.V.m.V.m.m.V.m.m.m.V.m.V.m.m.m.m.V.m.V.m.m.m.V.m.m.m.V.m.m.V.m.V.m.m.V.m.V.m.m.V.m.m.m.V.m.", -"V.m.m.m.m.m.m.V.V.m.m.m.m.m.m.V.m.m.m.V.m.V.V.m.m.V.V.m.V.m.m.m.m.m.m.V.m.V.V.m.V.m.m.V.m.V.V.m.m.V.m.V.V.m.V.m.V.m.V.m.m.k v.m.m.m.m.V.V.m.m.m.V.m.m.V.m.m.m.V.m.m.f m.m.m.V.m.m.m.m.V.m.. v m.m.m.V.V.m.m.l 0.m.m.V.V.m.V.*. 0.m.m.V.m.V.m.m.m.m.@ % m.m.V.V.m.m.m.. i V.m.m.V.m.9. #.m.m.m.V.m.V.m.V.m.F h.V.m.m.m.V.m.m.m.V.p v m.m.m.m.V.V.m.V.m.A 9.m.m.m.m.V.m.m.m.V.m.m.m.m.m.V.m.m.V.m.m.m.V.m.m.V.V.m.m.V.m.m.m.V.m.m.V.m.m.m.V.m.m.V.V.m.m.", -"m.m.m.m.m.m.m.m.V.m.m.m.m.m.m.m.m.m.V.m.m.m.m.m.V.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.k v.m.m.m.m.m.m.m.m.m.m.V.m.m.m.m.V.m.m.m.f m.m.m.m.m.m.m.m.m.m.. v m.m.m.V.m.m.m.#. c.m.m.m.m.m.m.*. . 0.m.m.m.m.m.m.m.m.m.@ @ m.m.m.m.V.m.m.. p m.m.V.m.m.9. $.m.V.m.m.m.V.m.m.m.D h.V.m.m.m.m.m.V.m.m.%. v m.m.m.m.V.m.m.m.m.C 9.m.m.m.m.m.m.m.m.V.m.m.m.m.m.V.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.V.m.m.m.V.m.", -"m.V.m.m.m.m.m.m.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.k v.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.a m.m.m.m.m.V.m.m.m.m.. v m.m.m.m.m.m.m.-. + m.m.m.m.m.m.m.*. 0.m.m.m.m.m.m.m.m.m.@ @ m.m.m.m.m.m.m.. p m.m.m.m.m.9. $.m.m.m.m.m.m.m.m.m.D h.m.m.m.m.m.m.m.m.m.0. v m.m.m.m.m.m.m.m.V.C 9.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.V.m.m.m.m.V.m.m.m.m.m.m.m.m.m.m.m.m.m.", -"m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.k v.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.a m.m.m.m.m.m.m.m.m.m.. k m.n.m.m.m.m.m.0. < m.m.m.m.m.m.m.*. 0.m.m.m.m.m.m.m.m.m.@ @ m.m.m.n.m.m.m.. . i m.m.m.m.m.9. $.m.m.m.m.m.m.m.m.m.S 0.m.m.m.m.m.m.m.m.m.m.< v m.m.m.m.m.m.m.m.m.C 9.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.", -"m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.k c.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.a v.m.m.m.m.m.m.m.m.m.. v m.m.m.m.m.m.m.b. a m.m.m.m.m.m.m.*. 0.m.m.m.m.m.m.m.m.m.@ @ m.m.m.m.m.m.m.. i m.m.m.m.m.9. $.m.m.m.m.m.m.m.m.m.#. h.m.m.m.m.m.m.m.m.n.m.S . v m.m.m.m.m.m.m.m.m.C 8.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.", -"m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.n.m.m.n.m.m.m.m.n.m.k c.m.m.n.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.a m.m.m.m.m.m.m.m.m.m.. v m.m.n.m.m.m.m.n.@ S m.m.m.m.m.m.m.*. 0.n.n.m.m.m.m.m.m.n.@ @ m.m.m.m.m.m.m.. i n.m.m.m.m.8. $.m.m.m.m.m.m.m.m.m.S h.n.m.n.m.m.m.m.m.m.m.8. v n.m.m.m.m.m.m.m.m.C 9.m.m.n.m.m.n.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.m.m.m.m.m.m.n.m.m.m.n.m.m.m.n.m.m.m.m.m.m.m.m.m.m.", -"m.m.m.m.m.m.n.m.n.m.m.n.n.m.m.n.m.m.m.m.m.n.n.m.n.m.m.n.m.m.m.n.m.m.m.n.n.m.n.m.m.n.n.m.m.m.m.m.n.m.n.m.m.m.m.m.m.m.m.m.n.k . c.n.n.m.m.m.n.m.n.m.m.m.n.m.m.n.n.m.m.m.a m.m.m.n.m.m.n.n.m.n.. k m.m.m.m.m.m.n.m.i &.n.m.n.m.m.m.n.*. 0.n.m.m.n.n.m.m.m.m.@ @ n.m.n.m.m.n.m.o i n.n.m.n.m.8. $.n.m.n.m.m.n.m.n.m.D h.m.m.m.m.m.m.n.n.m.m.n.+ v m.m.n.n.m.m.n.m.m.C 8.m.m.m.m.m.m.m.n.m.n.n.n.m.m.m.m.n.m.m.m.m.m.n.m.m.n.m.m.m.n.m.m.m.m.m.m.m.m.m.m.n.m.n.m.m.n.", -"m.m.n.m.m.n.n.m.m.n.m.n.n.m.m.n.m.n.n.m.m.m.m.m.n.m.m.n.n.m.m.n.m.n.n.m.n.m.m.n.n.m.m.n.m.n.n.m.m.m.m.m.m.n.n.m.m.n.n.m.m.k c.m.m.m.m.n.m.m.n.n.n.m.m.n.n.m.m.n.m.n.f . v.n.m.m.n.m.n.m.m.m.. v n.n.m.m.n.n.m.m.v 8.m.m.n.m.m.n.n.*. . 8.m.n.m.m.m.m.n.m.n.@ @ m.n.n.m.m.n.m.. i m.m.n.n.m.9. $.m.n.n.m.n.n.m.m.n.S h.n.n.m.m.n.n.m.m.n.m.m.k v g.n.m.n.m.n.m.m.n.C 8.n.m.m.n.n.m.n.m.m.m.m.m.m.n.n.m.m.n.n.m.b.n.n.m.m.n.n.m.m.m.n.m.m.n.n.m.m.n.n.m.m.n.n.m.m.n.", -"n.n.m.n.n.m.m.n.m.m.n.m.m.n.m.m.n.m.m.n.n.m.n.n.m.m.n.m.m.n.m.m.m.m.n.m.m.m.n.m.m.n.m.m.m.n.m.m.n.n.m.n.m.n.m.m.n.m.m.n.m.k X c.n.m.n.n.m.m.n.m.m.m.n.m.n.m.m.n.m.n.m.a . n.m.n.m.n.n.m.m.n.n.. v n.m.n.n.m.m.n.m.$. 0.n.m.m.n.m.m.n.*. 0.m.m.n.m.n.n.m.n.m.@ X @ m.m.m.n.m.m.n.. . i n.m.m.m.m.8. X $.m.m.m.n.m.m.n.m.m.S . h.n.m.n.n.m.m.n.m.m.n.m.=. v m.m.m.m.m.n.m.n.m.C X 8.m.m.n.m.m.m.m.n.n.m.m.n.n.m.m.n.m.n.m.m.n.m.m.n.m.m.n.m.n.m.m.n.n.m.m.n.n.m.m.n.m.n.m.m.n.m.", -"m.n.n.m.n.n.m.n.m.n.m.m.m.n.m.n.m.n.n.m.n.m.n.m.m.n.m.m.m.n.m.n.n.m.m.m.n.m.n.m.n.m.n.m.n.m.m.n.m.n.m.m.n.n.m.n.n.m.n.n.m.*.C C C C C C C C C C v C C C C C C C C C C C C C b.m.n.m.n.m.n.m.n.m.n.n.m.n.n.m.n.n.m.n.*.C C C C C C C C C C C C C v C C C C C C C C C C m.m.n.n.m.n.m.n.m.n.D S S S S S S S S S S S S S S S S S S S S -.m.n.m.n.m.n.m.m.0.S S S S S S S S S S S S S S S b.n.m.n.m.n.n.m.8.S D S S S S S S S S S S S S S S S D S S S h.m.m.n.m.n.m.n.m.m.D C C C C C C C C C C C C v C C C C C C C C C C C C C C C C C C C C C C v C C C C C #.n.m.m.n.m.m.m.S C C C C C C C C C C v C C C C C C C C C C C C C C C C C C C C C C C v C C C &.m.m.n.m.m.0.C C C C C C C C C C C C C C C C C C C C C C C C 8.n.m.n.m.m.m.m.m.n.-.S S S S S S S D S S S S S S S S S S S S c.m.n.m.n.m.n.m.m.m.n.n.c.S S S S S S S S S S S S S S S S S S S S S -.n.m.n.n.m.n.m.n.n.-.C C C C C C C C C v C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C 0.n.m.n.n.m.n.n.m.m.n.m.m.m.m.n.n.m.n.m.n.m.m.m.m.m.n.m.n.m.m.n.m.n.m.n.m.m.n.n.m.m.n.m.m.m.n.", -"m.n.m.n.m.n.n.m.n.m.n.n.m.n.n.m.m.n.m.n.m.n.n.n.n.m.n.n.n.m.n.m.n.n.n.n.m.n.n.n.n.m.m.n.n.n.n.m.n.m.n.n.n.m.m.n.m.n.n.m.n.n.n.m.n.m.n.n.n.m.n.n.m.n.n.m.n.n.n.m.m.n.n.n.n.m.n.m.n.n.m.n.n.m.n.m.n.m.n.m.m.n.m.n.n.m.n.n.n.m.n.n.n.m.n.n.n.m.n.n.m.n.n.m.n.n.n.m.m.n.n.n.m.n.m.n.n.n.m.n.m.n.m.n.m.n.m.n.m.n.n.n.m.n.m.n.n.n.m.n.n.n.n.n.n.m.n.m.n.n.n.n.n.n.n.n.n.n.m.n.m.n.n.m.n.n.m.n.n.n.m.n.n.m.n.m.n.n.m.n.m.n.n.n.n.m.n.m.n.n.m.n.n.n.m.n.n.m.n.n.n.n.m.n.n.n.n.n.n.n.n.m.m.n.n.n.n.m.n.m.n.m.n.n.m.n.m.n.m.n.n.n.n.m.n.m.n.n.n.m.m.n.n.m.n.n.m.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.m.m.n.n.m.n.m.n.n.m.n.n.n.m.n.m.n.n.m.n.n.n.m.n.n.n.m.n.n.m.n.n.m.n.n.m.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.m.n.n.n.n.m.n.m.n.n.m.n.m.n.m.n.m.n.n.n.n.n.m.m.n.m.m.n.m.n.n.n.m.n.n.m.n.m.n.n.n.m.n.n.n.n.n.m.n.n.n.n.n.n.n.m.n.n.m.n.n.n.n.m.n.m.n.m.n.m.m.n.m.n.n.m.n.m.m.n.n.m.n.n.m.n.n.m.m.n.m.n.n.n.n.m.n.m.n.m.n.n.m.n.m.n.m.n.n.n.n.m.n.m.m.n.n.m.n.m.n.n.n.m.n.m.n.m.n.n.m.n.n.n.n.m.n.m.m.n.n.m.n.n.n.n.n.m.n.m.n.m.n.n.n.n.m.n.n.n.n.n.n.n.m.n.m.n.n.m.n.n.n.n.n.n.m.n.", -"n.n.n.n.n.n.n.n.m.n.n.n.n.n.m.n.n.n.m.n.n.n.n.n.m.n.n.n.n.m.n.n.n.m.n.m.m.n.n.m.m.n.n.n.n.m.n.n.n.m.n.m.n.m.n.n.m.n.n.m.n.m.n.n.n.n.n.m.n.m.n.m.n.n.m.n.m.n.n.m.m.n.n.n.n.m.n.n.n.m.m.n.m.n.n.n.n.n.n.n.m.n.n.n.n.m.m.n.m.n.n.n.n.n.n.m.n.m.n.m.n.n.m.n.m.n.n.m.m.n.n.n.n.n.n.n.m.n.m.n.n.n.m.n.n.m.n.n.n.m.n.m.n.m.n.n.n.m.n.m.n.m.n.m.m.n.n.n.m.n.n.m.m.n.n.m.n.m.n.m.n.m.n.n.m.n.m.n.m.n.n.m.n.m.n.n.n.m.n.n.m.n.n.n.n.m.n.n.m.n.n.m.n.m.n.n.m.n.n.n.m.n.n.m.n.n.n.m.n.n.n.n.m.n.n.n.n.m.n.n.n.n.n.m.n.m.n.n.m.n.n.m.n.n.m.n.m.n.m.n.n.n.n.n.m.n.n.m.n.n.n.n.m.n.n.n.n.m.n.m.m.n.m.n.n.n.n.n.m.n.m.n.m.n.n.n.n.m.n.n.m.n.n.n.n.m.n.m.n.m.m.n.n.n.m.n.n.m.n.n.n.m.n.m.n.m.n.m.n.n.n.m.n.m.m.n.n.n.n.n.m.n.n.n.m.n.n.n.m.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.m.n.n.m.n.n.m.m.n.m.n.m.n.m.n.m.n.n.m.n.n.n.m.m.n.n.m.m.n.n.n.n.m.n.n.n.m.n.n.n.m.n.n.m.n.n.n.n.m.n.n.m.n.n.m.n.m.n.n.m.n.n.n.n.m.n.n.n.n.n.m.n.m.n.n.m.n.n.m.n.n.m.n.n.n.n.n.n.n.n.m.n.m.n.n.m.n.n.m.m.n.n.m.n.m.n.n.n.n.m.n.n.n.m.n.n.n.n.n.n.n.m.n.n.m.n.n.n.m.m.n.m.n.m.n.n.n.n.n.n.m.n.m.n.m.n.n.", -"n.n.n.m.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.", -"n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.", -"n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.m.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.", -"n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.g.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.g.n.n.n.n.n.n.n.g.g.n.n.g.n.n.n.n.n.n.n.g.g.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.b.n.n.n.g.n.n.g.n.n.n.n.g.n.n.g.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.g.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.g.n.g.n.n.n.n.g.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.g.n.n.g.n.n.n.n.b.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.g.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.n.n.n.n.n.n.n.n.g.n.g.n.n.n.n.g.n.n.n.n.n.g.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.g.g.n.n.g.n.g.n.n.n.n.n.g.n.n.g.g.n.n.n.g.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.", -"g.n.n.f.n.n.f.n.n.n.f.n.g.n.n.f.n.n.n.f.n.n.f.n.g.n.g.g.n.g.n.g.g.n.g.n.g.g.n.n.g.n.g.g.n.g.g.n.g.n.g.n.g.n.n.n.n.g.n.n.g.n.n.g.g.n.g.g.g.n.g.g.n.n.n.g.g.n.g.g.g.n.g.g.n.g.g.n.g.g.n.g.g.n.g.g.n.n.n.g.n.g.g.n.n.n.n.g.n.g.g.n.n.n.g.n.n.g.g.n.g.n.n.g.n.n.g.n.n.n.f.n.n.f.n.n.f.n.n.n.g.n.g.g.g.n.n.g.g.n.g.n.n.g.n.g.n.n.g.n.g.g.n.n.g.g.n.n.g.n.g.n.g.g.n.n.n.g.g.n.g.n.n.g.n.n.g.n.g.n.g.g.n.g.n.g.g.n.n.n.n.g.g.n.g.n.n.g.n.g.n.g.g.n.n.n.g.n.g.g.n.g.g.n.g.n.n.g.n.n.g.n.n.g.g.g.n.n.n.g.n.g.n.g.g.n.n.n.n.g.n.n.g.n.n.g.g.n.n.n.g.n.g.g.n.g.n.g.g.n.g.n.g.n.g.g.n.n.n.g.g.n.n.n.n.g.g.g.n.n.g.g.n.n.n.g.n.n.g.n.n.g.g.g.g.n.g.g.g.n.g.g.n.g.n.g.g.n.g.n.g.n.g.n.n.g.n.n.g.n.g.n.g.n.g.g.n.n.n.n.n.g.g.g.n.g.g.n.g.n.g.g.g.n.g.n.g.n.g.g.n.g.g.n.g.n.n.n.n.g.n.n.g.n.g.n.g.n.g.n.g.n.g.g.g.n.g.n.g.g.n.n.g.n.g.g.n.n.n.g.n.g.g.n.g.n.n.n.n.g.g.n.g.n.n.g.n.g.g.n.g.n.n.n.n.g.g.g.n.n.n.g.n.g.n.g.g.n.n.n.n.g.n.n.g.n.n.g.g.n.n.n.n.g.n.n.g.n.g.n.g.g.n.n.n.g.g.n.g.g.n.g.n.n.g.n.n.g.g.n.n.n.g.n.n.n.n.n.n.n.n.n.n.n.n.f.g.g.n.n.g.n.g.g.n.g.g.n.g.g.n.g.", -"n.n.g.n.g.n.g.g.n.g.n.n.n.n.g.n.n.n.g.n.n.g.n.n.g.n.n.g.n.g.n.n.n.n.g.n.n.g.n.n.g.n.g.n.g.n.n.g.b.g.g.g.g.b.g.b.g.b.g.n.g.b.g.b.g.n.g.n.g.g.n.g.g.n.g.n.g.n.g.g.g.n.g.n.g.g.n.g.n.n.n.n.g.n.n.n.g.n.n.g.g.n.g.n.n.n.g.n.n.n.g.n.g.n.n.g.n.g.n.n.g.n.n.n.g.n.n.g.g.b.g.b.g.g.g.b.g.b.g.g.g.g.b.g.b.g.b.g.g.g.b.g.g.g.g.g.g.b.f.b.n.g.n.g.n.n.g.n.g.g.g.n.n.g.n.g.n.g.n.g.n.n.g.n.n.n.g.n.n.g.n.n.g.g.n.g.n.g.n.n.g.n.n.n.g.n.n.g.g.n.g.g.n.g.n.g.n.n.g.n.n.n.g.n.n.n.g.n.g.n.g.g.n.g.n.n.n.n.g.n.b.g.g.g.g.b.g.b.g.b.g.n.g.b.g.b.n.g.n.g.n.n.g.n.g.g.g.n.g.n.g.n.g.n.n.n.g.n.n.g.n.n.n.n.g.n.n.n.n.n.g.n.n.g.g.n.n.g.g.n.n.g.g.n.g.g.n.g.n.g.n.n.g.n.g.n.g.g.n.g.g.b.g.b.g.g.g.b.g.b.g.g.g.g.b.g.b.g.b.g.g.g.b.g.g.g.g.g.g.b.f.b.n.g.n.g.n.n.g.n.n.n.g.n.g.n.g.g.n.g.g.n.g.n.n.g.n.n.n.n.g.n.n.n.n.g.n.n.g.g.g.n.n.g.n.g.n.n.g.n.n.g.n.n.g.n.g.n.g.g.n.g.n.n.n.n.g.g.n.g.n.n.n.n.g.n.n.n.g.n.n.g.b.g.g.g.g.b.g.b.g.b.g.n.g.b.g.b.n.g.n.g.n.n.g.n.g.g.n.n.g.n.n.n.g.g.n.g.n.n.g.n.n.n.g.n.n.g.n.n.g.n.n.g.g.n.n.g.n.n.n.n.n.n.n.n.n.g.n.g.g.n.g.n.n.g.n.g.n.n.g.n.", -"f.n.n.f.n.g.g.n.n.g.f.n.f.n.n.f.g.g.g.g.g.g.f.n.n.f.n.g.g.n.f.n.f.n.n.f.g.g.f.n.n.f.n.g.f.n.n.f.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.n.g.f.n.f.n.g.g.g.n.g.g.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.b.g.b.g.f.b.b.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.n.n.f.f.n.g.n.g.g.g.n.g.g.n.f.g.g.f.n.n.f.g.g.g.n.n.g.g.n.f.n.g.g.g.g.f.n.g.g.g.g.n.g.g.n.g.g.f.n.f.n.n.f.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.n.f.n.n.f.n.f.g.g.g.g.g.n.g.g.g.n.g.g.g.n.g.g.g.n.n.g.g.g.g.g.g.g.n.g.g.n.n.g.g.g.g.g.g.g.g.g.g.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.b.g.b.g.f.b.b.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.n.f.n.g.g.n.f.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.n.n.f.f.n.f.n.g.n.n.g.f.n.f.n.n.f.g.n.f.n.g.g.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.g.g.g.g.f.n.n.f.n.g.f.n.f.n.f.n.g.n.f.n.f.n.f.n.f.n.f.f.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.", -"g.g.f.n.n.g.g.n.f.f.n.n.g.n.g.g.g.g.g.g.g.g.g.g.g.n.f.g.g.g.g.g.g.n.f.n.n.g.g.g.g.n.g.g.f.n.g.g.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.n.g.n.g.f.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.f.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.n.n.n.g.n.f.g.g.n.g.g.g.g.g.g.g.n.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.f.g.g.g.f.n.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.n.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.f.f.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.g.g.g.g.n.g.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.f.n.g.g.g.g.g.g.f.n.f.g.g.g.g.g.g.g.g.f.g.g.g.g.g.g.g.b.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.n.f.g.g.n.n.g.n.g.g.g.n.g.f.n.n.f.n.f.n.n.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.", -"f.n.f.f.f.g.f.f.f.n.f.f.f.f.g.f.f.g.g.g.g.g.f.g.f.g.f.g.g.f.g.f.f.f.g.f.g.f.g.f.f.f.f.n.f.f.n.f.g.f.g.f.f.g.g.g.g.g.g.f.g.g.g.f.g.g.g.f.g.g.g.g.g.f.g.g.g.g.g.g.g.g.g.g.g.f.g.g.f.g.f.f.f.f.f.n.f.g.g.g.f.g.g.f.g.g.g.f.g.g.g.f.g.g.g.g.g.g.f.g.g.g.f.g.f.f.g.f.b.f.g.f.g.g.g.g.g.g.g.g.f.g.g.f.g.f.g.g.g.g.g.g.g.g.f.g.f.g.b.f.g.g.g.g.g.g.f.g.f.g.g.g.g.g.g.g.g.g.g.g.f.g.g.g.n.f.f.f.f.g.f.n.f.f.g.g.g.f.g.f.f.f.f.g.f.n.f.f.g.g.g.f.f.g.f.g.f.n.f.f.n.f.g.f.g.f.g.g.g.f.g.g.f.g.f.n.f.n.f.f.g.f.g.f.f.g.g.g.g.g.g.f.g.g.g.f.g.g.f.g.f.g.g.g.g.g.f.g.g.g.g.g.g.g.g.f.g.g.g.g.n.f.f.n.g.f.f.g.g.f.g.f.g.g.f.g.g.g.f.g.g.g.f.g.g.f.g.g.g.f.g.g.g.g.g.f.f.g.f.f.b.f.g.f.g.g.g.g.g.g.g.g.f.g.g.f.g.f.g.g.g.g.g.g.g.g.f.g.f.g.b.f.g.g.f.g.g.g.g.g.g.g.f.g.g.g.f.g.g.g.g.g.g.g.g.g.f.g.f.g.f.f.f.g.f.g.g.g.f.g.g.g.g.g.g.g.f.g.g.g.g.f.g.g.f.g.g.f.f.f.n.f.g.f.g.g.g.f.n.f.g.f.g.g.f.g.f.n.f.n.f.f.g.f.g.f.f.g.g.g.g.g.g.f.g.g.g.f.g.f.g.f.f.n.f.f.f.g.g.f.g.g.g.f.g.g.f.g.g.g.g.g.n.f.f.f.f.n.f.f.f.f.f.n.f.f.f.f.n.f.f.f.n.f.f.f.g.g.g.g.g.f.g.f.g.g.g.g.f.g.g.g.", -"f.n.g.f.g.g.g.g.f.g.g.f.g.f.n.f.g.g.g.g.f.g.g.g.f.n.g.f.g.f.g.g.g.f.g.f.g.f.g.g.g.f.g.g.n.n.f.f.f.f.b.g.f.b.f.b.f.g.g.g.f.g.g.g.g.g.f.g.g.g.g.g.g.g.f.g.g.g.g.g.g.g.g.g.g.g.f.g.g.f.g.g.f.f.f.n.g.g.f.n.g.g.g.g.f.g.g.g.g.f.g.g.g.f.g.g.g.f.g.g.g.f.f.g.n.g.f.n.f.b.f.g.f.f.f.f.f.g.g.g.f.g.g.g.g.g.g.g.g.g.f.g.g.g.f.g.f.f.f.f.g.f.f.g.f.g.g.f.g.g.g.g.f.g.g.g.f.g.g.g.g.g.f.g.f.n.f.f.n.f.f.f.g.f.g.f.g.g.g.g.g.g.f.g.n.g.f.n.g.g.g.g.g.g.g.f.f.n.g.f.g.f.g.g.f.g.g.f.g.f.g.f.f.g.g.f.f.f.n.f.f.f.b.g.f.b.f.b.f.g.g.g.f.g.g.g.g.g.g.g.g.g.f.g.g.f.g.g.g.g.f.g.g.g.f.g.g.g.g.g.f.n.f.f.n.f.n.f.f.f.g.f.g.f.g.g.g.g.g.g.g.g.f.g.g.g.g.g.g.g.g.g.g.f.g.g.f.f.g.f.f.b.f.g.f.f.f.f.f.g.g.g.f.g.g.g.g.g.g.g.g.g.f.g.g.g.f.g.f.f.f.f.g.g.g.g.f.g.g.g.g.f.g.f.g.g.f.g.g.g.f.g.g.g.g.g.f.g.f.f.g.g.n.f.g.g.g.f.g.g.g.f.f.g.g.g.g.g.g.f.g.g.f.g.g.g.g.g.n.f.f.g.f.n.g.f.f.n.g.f.g.f.g.f.g.g.f.g.g.f.n.f.f.f.b.g.f.b.f.b.f.g.g.g.f.g.g.g.f.g.f.g.f.f.n.f.g.g.g.g.g.g.g.g.g.g.g.g.f.g.g.g.n.f.f.n.n.f.f.f.n.n.f.g.f.n.f.n.f.n.f.n.f.f.n.n.g.f.g.f.g.g.g.g.f.g.g.g.g.g.g.f.", -"g.f.f.g.g.f.f.g.g.f.g.g.f.g.g.f.f.g.f.f.g.g.f.f.f.f.f.g.g.g.f.g.f.g.g.f.g.g.f.g.g.g.f.g.f.f.g.g.f.b.f.f.f.f.f.f.g.f.g.f.g.f.g.f.f.f.g.g.f.f.g.f.g.f.g.f.f.f.f.g.f.f.f.g.f.g.g.f.f.n.g.f.n.n.f.f.g.f.f.f.f.g.f.g.g.f.f.f.f.f.g.f.f.g.f.g.f.g.f.g.f.g.g.g.f.f.f.f.g.f.f.g.f.f.b.f.g.f.g.f.g.f.g.f.f.f.g.f.g.f.g.f.f.g.g.f.b.f.b.f.f.g.g.g.g.f.f.g.f.g.f.f.g.g.f.g.g.g.f.g.f.g.f.g.f.n.f.n.f.n.f.f.g.g.f.g.g.f.f.g.f.f.g.g.f.f.f.f.f.g.f.g.f.g.f.f.f.f.f.g.g.g.f.g.f.g.g.g.g.g.g.f.g.g.f.g.g.g.g.f.f.b.f.f.f.f.f.f.g.f.g.f.g.f.g.f.f.g.f.f.g.f.f.g.g.g.f.g.f.f.g.g.f.f.g.g.f.f.g.f.g.g.f.g.f.f.f.f.g.g.g.g.g.g.f.g.f.f.g.f.f.f.g.f.f.f.f.g.f.f.f.g.g.g.f.g.g.g.g.g.g.f.f.g.f.f.b.f.g.f.g.f.g.f.g.f.f.f.g.f.g.f.g.f.f.g.g.f.b.f.b.f.f.g.f.f.g.f.f.f.f.n.f.n.f.f.g.g.f.f.g.g.f.f.g.f.g.g.g.g.f.f.f.f.g.f.g.g.g.f.g.g.g.g.f.g.f.g.f.g.g.f.g.f.f.f.f.f.g.f.g.g.f.f.f.g.f.f.g.g.f.g.f.g.f.f.g.g.f.g.n.f.f.b.f.f.f.f.f.f.g.f.g.f.g.f.g.f.g.f.g.g.n.f.f.g.f.g.f.g.f.g.f.f.f.g.f.f.g.f.f.f.f.n.g.f.f.f.n.f.f.f.g.f.g.f.g.f.f.f.f.f.n.f.f.f.g.g.f.g.g.f.f.g.g.g.f.g.f.g.f.g.", -"f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.g.f.f.f.f.f.f.g.f.f.f.g.f.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.g.f.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.b.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.g.f.f.f.f.f.g.f.f.f.f.f.g.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.g.f.g.f.f.f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.b.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.g.f.f.f.f.g.f.f.f.f.g.f.g.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.f.f.f.g.f.f.f.f.f.n.f.f.f.f.f.f.g.f.g.f.f.f.g.f.f.f.f.f.f.f.f.f.g.f.f.", -"f.f.f.f.f.f.g.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.g.f.g.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.g.f.g.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.g.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.", -"f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.", -"f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.c.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.c.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.c.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.", -"f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.c.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.d.f.f.d.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.d.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.c.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.", -"d.f.d.f.f.d.f.f.f.d.f.d.f.f.d.f.f.d.f.f.f.d.f.d.f.f.f.f.f.d.f.d.f.f.f.f.d.f.d.f.f.d.f.f.d.f.d.f.f.d.f.d.d.f.d.f.f.d.c.d.f.d.d.f.f.f.d.f.f.d.f.f.f.d.f.d.f.d.f.f.d.f.f.f.d.f.d.f.f.d.f.d.f.f.f.f.f.d.f.d.f.f.d.f.d.f.f.f.f.d.f.f.f.f.f.f.f.d.d.f.f.d.f.f.d.f.d.f.d.f.f.d.f.d.f.f.f.f.f.f.d.f.d.f.f.d.f.f.f.d.f.f.d.f.f.f.d.f.d.f.d.f.f.d.d.f.d.f.f.d.f.d.f.f.d.f.f.d.f.f.f.d.f.d.f.f.f.f.f.f.d.f.f.d.f.f.f.d.d.f.f.d.f.d.d.f.f.d.f.f.d.f.d.f.d.f.f.d.f.d.f.f.f.f.d.f.d.f.f.d.f.d.d.f.f.d.f.f.f.d.f.d.f.d.d.f.d.f.f.d.c.d.f.d.d.f.d.f.f.d.f.d.f.f.d.f.d.f.f.f.d.f.d.f.f.f.d.f.d.f.d.f.f.d.f.f.d.f.f.f.f.f.f.d.f.f.d.f.f.d.f.d.f.f.f.f.f.f.d.f.d.f.f.d.f.f.d.f.d.f.d.f.f.d.f.d.f.f.f.f.f.f.d.f.d.f.f.d.f.f.f.d.f.f.d.f.f.f.d.f.d.f.d.f.f.d.f.d.f.f.f.d.f.d.f.d.f.d.d.f.f.f.f.d.f.f.f.d.f.d.f.d.f.d.d.f.d.f.f.d.d.f.f.f.f.d.d.f.d.f.f.d.f.f.d.f.f.d.d.f.f.f.f.d.f.d.f.f.f.f.d.f.d.f.f.d.f.d.d.f.f.d.f.d.f.d.d.f.d.f.f.d.c.d.f.d.d.f.d.f.f.d.d.f.d.f.f.f.f.d.f.f.d.f.d.f.f.f.d.f.d.f.d.f.f.d.f.f.d.f.f.f.d.f.d.f.f.d.f.d.f.f.d.f.d.f.d.f.d.f.f.d.f.d.f.f.f.d.f.d.f.d.", -"f.f.d.f.d.f.f.d.d.f.f.d.d.f.d.f.d.f.f.d.d.f.f.d.d.f.d.f.f.d.f.f.d.f.f.d.f.f.d.f.f.d.f.f.f.f.d.f.f.d.f.f.f.f.d.f.f.d.f.f.f.f.d.f.d.f.f.d.f.f.f.d.d.f.f.f.d.f.f.d.f.d.d.f.f.d.d.f.d.f.d.f.d.f.d.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.f.d.f.f.f.d.d.f.f.f.d.f.f.d.f.f.d.f.f.d.d.f.f.d.f.d.f.f.f.f.d.f.d.d.f.d.f.d.f.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.d.f.d.f.d.f.d.f.f.f.d.f.f.f.d.f.d.f.d.f.d.f.f.d.f.f.f.d.f.f.f.d.d.f.f.f.d.f.f.f.d.f.f.d.d.f.f.d.f.f.d.f.d.d.f.f.d.f.d.f.f.f.f.f.f.d.d.d.f.f.f.d.f.f.f.f.d.f.f.d.f.f.f.f.d.f.f.d.f.d.f.d.f.d.f.f.f.d.f.d.d.f.f.f.f.d.f.f.f.d.f.d.f.d.f.d.f.d.d.f.f.d.d.f.f.d.f.d.f.f.d.f.f.d.d.f.f.d.f.f.d.f.f.d.f.f.f.f.d.f.f.d.f.f.d.f.f.d.d.f.f.d.f.d.f.f.f.f.d.f.d.d.f.d.f.d.f.f.f.d.d.f.f.d.f.d.f.d.f.d.d.f.f.f.d.f.f.f.f.f.f.d.f.f.f.d.d.f.f.f.d.f.f.f.f.f.d.f.d.f.d.d.d.f.f.f.f.f.f.d.d.f.f.d.d.f.f.d.f.f.d.f.f.d.f.f.d.f.f.d.f.d.f.f.f.f.d.f.f.d.f.f.f.d.f.f.f.f.d.f.f.d.f.f.f.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.f.f.d.f.d.d.f.d.f.f.f.f.d.f.d.f.f.f.d.f.f.d.d.d.f.d.", -"d.f.f.d.f.d.d.f.f.f.d.f.f.d.d.f.f.f.d.f.f.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.f.d.f.f.d.f.f.d.d.f.f.f.d.f.d.d.f.f.d.f.f.d.d.f.f.d.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.f.f.d.f.f.f.d.f.f.f.d.f.f.f.f.d.f.f.f.d.d.f.f.d.d.f.f.f.d.f.f.d.d.f.d.f.f.d.f.f.f.f.d.f.d.f.f.d.d.f.f.d.f.f.f.d.d.f.d.f.f.d.d.d.f.f.f.f.f.f.d.f.f.d.f.f.f.d.d.f.f.d.d.f.f.f.d.f.f.f.d.f.f.f.d.f.d.f.d.f.d.f.d.f.f.f.d.f.f.f.d.f.f.d.f.d.f.d.d.f.f.f.d.f.f.d.d.f.f.d.d.f.f.f.d.f.f.d.f.f.f.f.d.f.f.d.f.f.d.f.d.d.f.f.f.f.f.d.f.f.d.f.d.d.f.f.d.f.f.d.d.f.f.d.f.f.f.d.f.f.f.d.f.d.f.d.f.f.f.d.f.d.d.f.f.d.f.d.f.f.f.d.f.f.f.d.f.d.f.f.f.d.d.f.f.d.d.f.f.d.f.f.f.d.d.f.d.f.f.d.f.f.d.f.f.d.d.f.f.d.d.f.f.d.f.f.f.d.d.f.d.f.f.d.d.d.f.f.f.f.f.f.d.f.f.d.f.f.f.d.f.f.f.d.f.f.f.d.d.f.d.f.d.f.d.f.f.d.d.f.f.d.d.f.d.f.d.f.d.f.d.f.f.d.f.d.f.f.f.f.f.f.d.d.f.d.d.f.f.f.d.f.f.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.f.d.d.d.f.f.d.f.f.d.f.f.d.f.d.d.f.f.d.f.f.d.d.f.f.d.f.f.f.f.f.f.f.f.d.f.f.f.d.f.f.f.f.f.f.f.f.f.f.f.d.f.f.d.d.f.f.d.d.f.f.f.d.f.f.d.f.f.f.f.f.f.d.d.d.f.f.d.f.d.d.f.f.d.f.f.f.f.f.f.", -"f.d.d.f.f.f.f.d.d.f.d.f.d.f.f.d.f.d.f.f.d.f.d.f.f.d.f.d.d.f.f.d.d.f.f.d.d.f.d.f.d.d.d.d.f.d.d.f.d.d.f.d.d.f.f.d.d.f.d.d.d.f.c.d.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.d.f.f.d.d.f.f.d.f.f.f.d.d.f.d.f.d.f.f.d.d.f.d.f.d.d.d.d.f.d.d.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.f.d.f.d.d.f.d.d.d.f.d.f.d.d.c.d.f.f.d.f.f.f.d.d.f.f.d.d.f.f.d.d.d.f.d.d.d.d.f.d.f.f.d.d.f.f.d.d.d.f.d.f.d.f.f.d.f.d.f.d.d.d.d.f.f.d.d.f.f.d.f.d.f.d.d.f.f.d.d.f.f.d.d.f.d.d.f.d.d.f.f.d.d.f.d.d.d.d.f.d.d.f.f.d.d.f.d.d.d.f.c.d.d.d.f.f.d.d.f.f.d.d.d.f.d.d.d.f.d.d.f.f.d.d.d.f.d.f.d.f.d.f.d.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.f.d.f.d.d.d.d.f.d.d.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.f.d.f.d.d.f.d.d.d.f.d.f.d.d.c.d.d.d.f.f.d.d.f.f.d.d.f.d.d.d.f.d.d.d.f.f.d.d.f.f.d.d.f.d.d.d.f.d.f.d.d.f.f.d.d.f.d.d.d.f.f.d.f.d.f.d.d.f.d.f.d.f.f.d.d.f.d.f.f.d.d.f.f.d.d.f.f.d.d.f.f.d.d.d.d.d.d.d.f.d.d.f.f.d.d.f.d.d.d.f.c.d.d.f.d.d.d.f.d.d.f.f.d.d.f.f.d.d.d.d.d.d.d.f.d.d.f.f.d.f.f.f.d.f.f.d.f.d.f.f.d.f.f.d.d.f.d.d.d.f.f.d.d.f.d.f.f.d.d.f.f.d.d.f.d.d.", -"d.f.d.d.d.d.d.f.d.d.d.f.d.d.f.d.d.d.d.d.d.d.f.d.d.d.f.d.f.d.d.f.d.d.f.d.d.f.d.d.f.d.f.d.d.f.d.d.f.d.d.d.f.d.d.d.f.d.d.f.d.d.d.d.d.f.d.d.d.f.d.d.f.d.d.d.f.d.d.d.d.d.f.d.d.d.f.d.d.d.d.f.d.d.d.f.d.d.d.f.d.d.f.d.d.d.d.f.d.d.d.f.d.d.f.d.d.f.d.d.f.d.f.d.d.f.d.d.f.d.d.f.d.d.d.f.d.d.f.d.f.d.d.d.f.d.d.d.f.d.d.f.d.f.d.d.f.d.d.d.d.d.f.d.d.d.f.d.d.d.d.f.d.d.d.f.f.d.d.f.f.d.d.f.d.d.d.f.d.d.d.f.f.d.d.d.d.f.d.d.f.d.d.d.f.f.d.d.d.f.d.d.f.d.d.d.d.f.d.d.d.d.f.d.d.f.d.d.f.d.d.f.d.d.d.d.f.d.d.f.f.d.d.d.f.d.d.d.f.d.d.f.d.d.d.d.d.f.d.d.d.f.d.d.d.f.f.d.d.f.f.d.d.f.d.d.d.f.f.d.d.d.f.d.d.d.f.d.d.d.d.f.d.d.d.f.f.d.d.f.d.d.d.f.d.d.f.d.d.f.d.d.d.f.f.d.d.f.d.d.f.d.d.f.d.d.d.f.d.d.f.d.f.d.d.d.f.d.d.d.f.d.d.f.d.f.d.d.f.d.d.d.d.f.d.d.d.f.d.d.f.d.d.f.f.d.d.f.d.f.d.d.d.f.d.d.f.d.d.f.f.d.d.f.d.f.d.d.d.d.f.d.d.f.d.f.d.d.f.d.d.d.f.d.d.d.f.d.d.f.d.d.f.d.d.f.d.d.f.d.f.d.d.d.f.d.d.d.f.f.d.f.f.d.d.d.f.d.d.d.f.d.d.f.d.d.d.d.d.d.f.d.d.d.f.d.d.d.f.d.d.d.f.d.d.f.f.d.d.d.f.d.d.d.f.d.d.d.f.d.f.d.d.d.d.d.d.d.d.d.f.d.d.f.f.d.d.f.d.d.f.d.d.f.d.d.d.f.d.d.d.f.", -"d.d.f.d.d.d.d.f.d.d.d.d.f.d.d.d.d.d.d.d.d.d.f.d.d.f.f.d.d.f.d.d.c.s.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.c.d.d.d.d.d.d.d.c.d.d.d.d.d.d.c.d.d.d.c.d.d.d.c.d.d.d.d.d.d.d.d.c.d.d.d.d.d.s.d.d.d.s.d.f.f.d.d.f.d.d.d.d.d.d.d.d.f.d.d.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.c.d.d.d.d.d.d.d.c.d.d.d.d.d.d.c.d.d.d.c.d.d.d.c.d.d.d.d.d.d.d.d.c.d.d.d.d.d.s.d.d.d.s.d.d.d.d.d.d.d.d.d.d.f.d.d.f.f.d.d.f.d.d.d.d.d.d.d.d.d.f.d.d.d.d.c.s.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.c.d.d.d.d.d.d.d.c.d.d.d.d.d.d.c.d.d.d.c.d.d.d.c.d.d.d.d.d.d.d.d.c.d.d.d.d.d.s.d.d.d.s.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.f.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.c.d.d.d.d.d.d.d.c.d.d.d.d.d.d.c.d.d.d.c.d.d.d.c.d.d.d.d.d.d.d.d.c.d.d.d.d.d.s.d.d.d.s.d.d.d.f.d.d.f.d.d.d.d.f.d.d.f.d.d.d.d.d.d.d.d.d.d.d.f.d.d.f.d.d.c.s.d.d.d.d.d.d.d.d.d.d.d.c.s.d.d.d.d.d.d.c.d.d.d.d.d.d.d.c.d.d.d.d.d.d.c.d.d.d.c.d.d.d.c.d.d.d.d.d.d.d.d.c.d.d.d.d.d.s.d.d.d.s.d.d.d.d.d.d.d.d.d.d.f.d.d.d.d.d.d.f.d.d.d.d.f.d.d.d.d.f.d.d.f.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.f.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.c.d.d.d.c.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.c.d.d.d.d.d.d.d.d.d.d.c.d.d.d.h.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.d.d.d.d.d.d.d.f.d.d.d.f.d.d.f.f.d.d.d.d.d.d.c.d.d.d.c.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.c.d.d.d.d.d.d.d.d.d.d.c.d.d.d.h.d.d.d.f.f.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.f.d.d.d.d.d.f.d.d.d.d.d.c.d.d.d.c.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.c.d.d.d.d.d.d.d.d.d.d.c.d.d.d.h.d.d.f.d.d.f.d.d.d.d.f.d.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.f.f.d.d.f.d.d.d.d.d.c.d.d.d.c.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.c.d.d.d.d.d.d.d.d.d.d.c.d.d.d.h.d.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.d.c.d.d.d.c.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.c.d.d.d.d.d.d.d.d.d.d.c.d.d.d.h.d.d.d.f.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.d.d.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.f.d.d.d.d.d.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.", -"d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.", -"d.d.s.d.d.d.d.d.s.d.d.d.d.d.s.d.d.d.d.d.s.d.s.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.s.s.d.d.s.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.s.d.d.d.d.d.s.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.s.d.d.d.d.s.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.d.d.d.d.", -"d.d.d.d.d.d.d.s.d.d.d.d.s.d.d.d.s.d.d.d.d.d.d.d.s.d.d.d.d.d.s.d.d.d.d.s.d.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.s.d.d.d.s.d.d.d.s.d.d.s.d.s.s.d.d.d.d.d.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.s.d.d.d.s.d.d.d.s.d.d.s.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.s.d.d.d.d.d.d.s.d.d.d.s.d.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.s.d.d.d.s.d.d.d.s.d.d.s.d.s.d.d.s.d.d.d.d.d.d.d.s.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.s.d.d.d.s.d.d.d.s.d.d.s.d.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.d.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.s.d.d.d.s.d.d.d.s.d.d.s.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.s.d.d.d.d.d.d.d.d.d.d.s.d.d.d.d.d.d.s.", -"s.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.s.s.d.s.d.d.d.d.d.d.d.d.d.d.s.d.d.s.s.d.s.h.s.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.s.d.d.s.d.s.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.d.s.d.d.s.s.d.d.d.s.s.d.d.s.s.d.d.s.d.d.s.d.s.s.d.s.d.d.s.s.d.s.h.s.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.s.d.d.s.d.s.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.d.d.d.d.d.s.d.s.d.d.d.d.d.d.d.s.d.d.s.s.d.d.s.s.d.s.h.s.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.s.d.d.s.d.s.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.s.d.s.d.d.d.s.d.d.s.s.d.s.d.d.d.d.s.d.d.s.s.d.d.d.s.d.s.s.d.d.s.s.d.d.s.s.d.s.h.s.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.s.d.d.s.d.s.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.d.d.d.d.d.d.s.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.d.d.d.d.d.s.d.s.d.d.s.s.d.s.h.s.d.d.d.d.d.s.d.d.s.d.s.s.d.s.d.d.d.d.d.d.s.d.d.d.s.s.d.d.s.s.d.d.s.s.d.d.s.d.s.d.d.d.d.d.s.s.d.d.d.d.d.d.d.s.d.d.s.d.s.s.d.d.s.d.s.s.d.s.d.s.d.d.d.s.d.d.s.d.d.d.d.d.d.d.d.d.d.", -"s.d.s.d.d.s.d.d.s.d.s.s.d.s.s.d.s.d.d.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.d.d.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.d.s.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.s.d.s.d.s.d.d.d.s.s.d.s.s.d.s.d.s.d.d.d.s.s.d.d.d.s.d.d.d.s.d.s.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.d.s.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.s.d.s.d.s.d.d.d.d.d.s.d.d.s.d.s.d.s.s.d.s.s.d.s.d.d.s.d.s.s.d.d.s.s.d.d.s.d.d.d.s.d.d.d.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.d.s.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.s.d.s.d.s.d.d.d.s.d.d.s.s.d.s.d.s.d.d.s.d.s.d.s.d.d.s.d.d.d.s.s.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.d.s.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.s.d.s.d.s.d.d.d.s.s.d.s.d.s.d.s.d.s.s.d.s.s.d.d.d.s.d.d.d.s.d.s.d.s.d.s.s.d.s.d.s.d.d.d.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.d.s.d.s.d.s.s.d.d.s.d.d.d.s.d.s.d.d.d.s.d.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.s.d.s.d.s.d.d.s.d.d.s.d.d.s.d.d.s.d.d.s.d.d.d.s.d.d.s.s.d.d.s.d.s.s.d.s.s.d.s.", -"s.s.d.s.d.s.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.d.d.s.s.d.d.s.d.s.s.d.s.s.d.s.d.s.s.s.d.s.s.d.s.s.s.s.d.d.s.d.s.d.s.s.d.s.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.h.s.s.s.d.d.s.s.s.d.s.d.s.d.s.s.d.s.d.s.s.d.s.s.d.s.d.d.s.d.s.s.d.s.d.s.s.d.s.s.s.d.s.d.s.s.s.d.s.s.d.s.s.s.s.d.d.s.d.s.d.s.s.d.s.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.h.s.s.s.d.d.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.d.d.s.s.d.d.s.s.d.s.s.d.s.s.d.s.s.s.s.d.s.d.s.s.s.d.s.s.d.s.s.s.s.d.d.s.d.s.d.s.s.d.s.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.h.s.s.s.d.d.s.s.d.s.s.s.s.d.s.d.d.s.d.s.s.d.s.s.d.d.s.d.s.s.d.d.s.s.d.s.d.s.s.s.s.d.s.d.s.s.s.d.s.s.d.s.s.s.s.d.d.s.d.s.d.s.s.d.s.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.h.s.s.s.d.d.s.s.s.d.s.d.s.s.d.s.d.s.s.s.s.d.d.d.s.s.d.s.d.d.s.s.d.d.s.d.s.s.d.s.s.d.s.d.s.s.s.d.s.s.d.s.s.s.s.d.d.s.d.s.d.s.s.d.s.d.s.d.s.d.d.s.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.h.s.s.s.d.d.s.d.d.s.d.s.d.s.s.d.s.s.d.s.d.s.s.d.s.d.s.s.d.s.d.s.s.d.s.s.d.s.d.", -"d.s.s.d.s.s.d.s.d.s.s.d.s.d.s.d.s.s.d.s.d.s.s.d.s.s.s.d.s.d.d.s.d.s.s.d.d.s.d.s.s.d.s.s.s.h.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.s.d.d.s.d.s.d.s.s.d.s.s.s.s.s.s.s.d.d.s.s.d.s.d.s.d.d.s.s.s.d.s.s.d.d.s.d.s.s.d.s.s.d.s.d.s.s.d.s.d.d.s.s.d.d.s.d.s.s.d.s.s.s.h.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.s.d.d.s.d.s.d.s.s.d.s.s.s.s.s.s.s.d.s.d.d.s.s.d.d.s.s.d.s.d.s.d.s.s.s.s.d.s.s.d.s.s.s.d.s.d.d.s.s.d.d.s.s.d.d.s.d.s.s.d.s.s.s.h.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.s.d.d.s.d.s.d.s.s.d.s.s.s.s.s.s.s.d.d.s.s.d.d.s.s.d.s.s.s.s.d.s.s.d.d.s.s.d.s.d.s.s.s.d.d.s.d.s.s.d.d.s.s.d.d.s.d.s.s.d.s.s.s.h.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.s.d.d.s.d.s.d.s.s.d.s.s.s.s.s.s.s.d.s.d.d.s.s.d.d.s.d.s.s.d.d.s.s.s.s.s.d.s.d.s.s.d.d.s.s.s.s.d.d.s.d.s.s.d.d.s.d.s.s.d.s.s.s.h.s.s.s.s.d.s.d.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.d.s.d.s.d.s.d.s.s.d.s.d.d.s.d.s.d.s.s.d.s.s.s.s.s.s.s.d.s.s.d.s.d.s.d.s.s.d.s.s.d.s.s.d.s.d.s.d.d.s.d.s.s.d.s.d.d.s.d.s.", -"s.d.s.d.s.d.s.s.s.d.s.d.s.s.s.s.d.s.s.d.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.s.s.d.s.d.s.d.s.d.s.s.h.a.s.s.s.s.d.s.d.s.d.s.s.d.d.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.d.s.d.s.d.a.s.s.s.d.s.d.s.s.d.s.d.s.s.s.s.s.d.d.s.s.d.d.s.s.s.d.s.s.d.s.s.s.d.s.d.d.s.s.d.s.d.s.s.s.d.s.d.s.d.s.d.s.s.h.a.s.s.s.s.d.s.d.s.d.s.s.d.d.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.d.s.d.s.d.a.s.s.s.d.s.d.s.s.s.s.s.d.s.s.d.d.s.s.d.s.s.s.s.s.d.d.s.s.d.s.d.s.s.d.s.s.d.s.d.s.d.s.s.s.d.s.d.s.d.s.d.s.s.h.a.s.s.s.s.d.s.d.s.d.s.s.d.d.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.d.s.d.s.d.a.s.s.s.d.s.d.s.s.d.d.s.s.d.s.s.s.d.d.s.d.s.d.s.s.s.d.s.s.d.s.s.s.d.s.d.s.d.s.d.s.d.s.s.s.d.s.d.s.d.s.d.s.s.h.a.s.s.s.s.d.s.d.s.d.s.s.d.d.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.d.s.d.s.d.a.s.s.s.d.s.d.s.d.s.s.s.d.s.s.s.s.d.d.s.s.d.s.s.d.s.s.d.s.s.s.s.s.d.s.d.d.s.s.s.s.d.s.s.s.d.s.d.s.d.s.d.s.s.h.a.s.s.s.s.d.s.d.s.d.s.s.d.d.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.d.s.d.s.d.s.d.a.s.s.s.d.s.d.s.s.s.s.s.d.s.d.s.s.d.d.s.d.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.s.s.s.h.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.s.s.s.h.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.s.s.s.h.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.s.s.s.h.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.d.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.d.s.s.d.s.s.s.s.s.s.d.s.d.s.s.s.s.s.s.s.s.s.h.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.d.s.d.s.s.d.s.s.", -"s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.d.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a.s.s.s.s.s.s.s.s.s.s.", -"s.s.s.a.s.a.a.s.a.s.s.s.a.a.a.a.s.s.s.s.s.a.s.s.s.a.s.s.a.a.s.s.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.s.a.a.a.a.a.s.a.s.s.s.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.s.s.s.s.s.s.a.s.a.s.s.s.a.a.a.a.s.s.s.s.s.s.a.s.s.s.s.s.s.s.a.s.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.s.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.a.s.s.s.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.s.s.a.s.a.s.s.s.s.a.s.s.a.a.8.a.s.s.s.a.s.a.s.s.s.a.s.s.a.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.a.s.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.a.s.s.a.s.s.s.a.a.h.a.a.a.h.s.a.s.s.s.a.s.s.a.s.s.s.s.s.s.s.a.s.s.s.s.a.a.a.a.a.s.s.s.a.s.a.s.s.s.s.s.s.a.a.s.s.", -"a.a.s.s.s.s.s.s.s.s.a.a.a.a.h.a.s.a.s.a.s.a.s.a.s.s.a.s.s.s.s.a.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.a.h.a.a.a.8.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.s.s.a.a.h.a.s.s.s.a.a.s.a.s.s.a.s.s.a.s.a.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.a.h.a.a.a.8.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.a.s.a.a.a.a.s.s.s.s.a.a.a.a.h.a.s.a.s.a.s.a.s.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.a.h.a.a.a.8.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.s.s.a.a.h.a.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.a.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.a.h.a.a.a.8.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.a.a.s.s.s.s.a.s.s.s.a.s.s.a.a.a.s.a.s.s.s.a.s.a.a.s.a.s.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.s.s.a.a.a.a.s.s.a.a.a.h.a.a.a.8.a.s.a.s.s.s.a.s.a.s.s.a.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.s.a.a.s.a.a.a.a.s.s.a.a.s.s.a.a.h.a.a.s.a.s.s.a.s.a.s.a.a.s.s.s.s.a.", -"s.s.a.s.a.s.s.a.s.a.a.a.a.a.a.a.s.s.a.s.s.s.a.s.a.s.s.s.s.s.s.a.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.a.a.a.h.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.s.s.s.s.s.a.a.a.a.a.a.s.a.s.a.s.a.a.s.s.a.s.a.a.s.s.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.a.a.a.h.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.a.s.s.s.s.a.s.a.s.s.a.s.a.a.s.s.a.s.a.s.a.s.a.s.s.s.s.a.s.a.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.a.a.a.h.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.s.s.a.s.s.a.a.a.a.a.a.s.a.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.a.a.a.h.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.a.s.s.a.a.s.s.a.s.a.a.a.s.s.a.s.s.s.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.a.a.s.s.a.a.a.h.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.s.s.a.s.a.a.a.a.a.a.s.s.a.s.a.s.s.s.s.a.s.a.s.s.s.s.s.a.s.s.a.a.a.a.a.a.a.s.s.s.s.s.s.a.a.s.a.s.s.a.s.a.", -"a.a.s.a.s.a.a.s.a.s.a.a.a.h.a.a.a.a.s.a.a.s.a.s.s.a.a.a.a.a.a.s.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.s.s.a.s.a.s.a.a.a.s.a.s.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.a.h.a.a.a.s.a.s.s.a.s.a.a.s.a.s.s.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.s.s.a.s.a.s.a.a.a.s.a.s.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.a.s.s.a.s.a.s.a.s.a.a.s.a.a.a.a.a.a.s.a.s.a.s.s.s.a.a.a.a.s.a.s.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.s.s.a.s.a.s.a.a.a.s.a.s.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.a.s.a.s.a.a.s.a.a.a.a.a.a.h.a.a.a.s.a.s.a.s.a.a.a.s.s.a.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.s.s.a.s.a.s.a.a.a.s.a.s.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.s.a.s.a.a.s.s.a.a.s.a.s.a.a.a.a.s.a.a.s.a.a.a.s.s.a.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.s.a.a.s.a.s.s.a.a.s.a.a.a.a.a.a.s.s.a.s.a.s.a.a.a.s.a.s.a.a.s.a.a.a.8.a.a.a.a.s.s.a.s.a.a.s.a.s.a.s.a.s.a.a.s.a.a.a.a.a.a.h.a.a.s.a.s.a.a.s.a.s.s.a.s.a.a.s.a.s.", -"s.s.a.s.a.s.a.s.a.a.s.a.a.a.a.a.a.s.s.a.a.s.s.a.a.s.a.s.s.a.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.s.a.a.s.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.s.s.a.a.a.a.a.a.s.a.s.a.s.a.a.s.a.s.s.a.a.s.a.s.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.s.a.a.s.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.a.a.a.s.a.a.s.a.a.a.a.a.a.s.s.a.a.s.s.a.s.a.a.a.s.s.a.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.s.a.a.s.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.s.s.a.a.a.a.a.a.s.a.a.s.a.a.a.s.a.s.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.s.a.a.s.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.s.a.a.a.s.a.a.a.s.a.s.a.a.a.a.a.s.a.s.a.s.s.a.a.s.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.s.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.s.a.a.s.s.a.a.a.a.a.a.a.a.a.a.s.s.a.a.s.s.a.a.a.s.a.a.a.s.s.s.s.a.a.a.a.a.a.a.a.a.s.a.s.s.a.a.a.a.s.s.a.s.a.", -"a.a.a.a.a.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.s.a.a.a.a.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.s.a.a.a.a.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.s.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.s.a.a.a.a.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.s.a.s.a.a.s.a.s.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.s.a.a.a.a.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.s.a.s.a.a.a.a.a.s.a.a.s.a.s.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.s.a.a.a.a.a.a.s.a.a.a.a.a.s.a.s.a.a.a.a.s.s.a.a.a.a.s.a.", -"a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.a.a.s.a.a.a.a.s.a.s.a.a.s.s.a.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.s.a.a.s.s.a.a.s.a.a.a.a.a.a.a.a.s.a.a.a.a.a.s.a.a.s.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.a.a.a.a.h.a.s.a.a.s.a.a.a.a.a.s.a.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.s.a.a.s.a.a.s.a.s.a.a.s.s.a.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.a.a.a.a.a.s.a.s.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.s.a.a.a.a.a.a.a.a.s.a.a.s.a.a.a.a.a.s.s.a.a.s.a.a.8.a.a.a.a.a.a.s.a.s.a.a.a.s.a.s.s.a.s.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.s.a.a.s.a.a.s.a.a.", -"a.s.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.s.a.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.s.a.s.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.s.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.a.s.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", -"a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a." -}; diff --git a/timeline/icons/icon-large.svg b/timeline/icons/icon-large.svg deleted file mode 100644 index 24ab03c..0000000 --- a/timeline/icons/icon-large.svg +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/timeline/icons/icon-small.svg b/timeline/icons/icon-small.svg deleted file mode 120000 index 1d9c2c6..0000000 --- a/timeline/icons/icon-small.svg +++ /dev/null @@ -1 +0,0 @@ -icon-large.svg \ No newline at end of file diff --git a/timeline/non-timeline.desktop.in b/timeline/non-timeline.desktop.in deleted file mode 100644 index a8ce62d..0000000 --- a/timeline/non-timeline.desktop.in +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Name=Non Timeline -Comment=Modular Digital Audio Workstation - Timeline Editor -Comment[fr]=Station de travail audio-numérique modulaire - Éditeur à ligne temporelle -Exec=@BIN_PATH@/non-timeline -Terminal=false -Type=Application -Icon=non-timeline -Categories=AudioVideo;Audio; diff --git a/timeline/src/Annotation_Point.H b/timeline/src/Annotation_Point.H deleted file mode 100644 index aaec594..0000000 --- a/timeline/src/Annotation_Point.H +++ /dev/null @@ -1,120 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Loggable.H" -#include "Sequence_Point.H" - -#include - -class Annotation_Point : public Sequence_Point -{ - -protected: - -// const char *class_label ( void ) { return "Annotation_Point"; } - - virtual void get ( Log_Entry &e ) const - { - Sequence_Point::get( e ); - - e.add( ":label", _label ); - } - - void - set ( Log_Entry &e ) - { - Sequence_Point::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":label" ) ) - label( v ); - } - -// timeline->redraw(); - } - - Annotation_Point ( ) - { - } - -public: - - /* for loggable */ - LOG_CREATE_FUNC( Annotation_Point ); - SEQUENCE_WIDGET_CLONE_FUNC( Annotation_Point ); - - Annotation_Point ( Sequence *sequence, nframes_t when, const char *label ) - { - _sequence = NULL; - - _r->start = when; - - _label = strdup( label ); - - sequence->add( this ); - - log_create(); - } - - Annotation_Point ( const Annotation_Point &rhs ) : Sequence_Point( rhs ) - { - log_create(); - } - - ~Annotation_Point ( ) - { - log_destroy(); - } - - - int - handle ( int m ) - { - Logger _log( this ); - - if ( m == FL_PUSH && Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() ) - { - const char *s = fl_input( "New label for mark:", label() ); - - if ( s ) - label( s ); - - return 0; - } - - int r = Sequence_Widget::handle( m ); - - if ( m == FL_RELEASE ) - { - sequence()->sort(); - redraw(); - } - - return r; - } - -}; diff --git a/timeline/src/Annotation_Region.C b/timeline/src/Annotation_Region.C deleted file mode 100644 index 83c374c..0000000 --- a/timeline/src/Annotation_Region.C +++ /dev/null @@ -1,125 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include - -#include "Annotation_Region.H" - - - -void -Annotation_Region::get ( Log_Entry &e ) const -{ - Sequence_Region::get( e ); - - e.add( ":label", _label ); -} - -void -Annotation_Region::set ( Log_Entry &e ) -{ - Sequence_Region::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":label" ) ) - label( v ); - } - -// timeline->redraw(); -} - -Annotation_Region::Annotation_Region ( Sequence *sequence, nframes_t when, const char *label ) -{ - _sequence = NULL; - - _r->start = when; - - /* FIXME: hack */ - _r->length = 400; - - _label = strdup( label ); - - sequence->add( this ); - - log_create(); -} - -Annotation_Region::Annotation_Region ( const Annotation_Region &rhs ) : Sequence_Region( rhs ) -{ - log_create(); -} - - -Annotation_Region::~Annotation_Region ( ) -{ - log_destroy(); -} - -void -Annotation_Region::draw_box ( void ) -{ - Sequence_Region::draw_box(); -} - -void -Annotation_Region::draw ( void ) -{ - draw_label( _label, (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_TOP | FL_ALIGN_CLIP ) ); -} - -#include -#include - -int -Annotation_Region::handle ( int m ) -{ - Logger _log( this ); - - if ( m == FL_PUSH ) - { - if ( test_press( FL_BUTTON3 ) ) - { - char *s = fl_text_edit( "Annotation text:", "&Save", label() ); - - if ( s ) - label( s ); - - free( s ); - - return 0; - } - } - - int r = Sequence_Region::handle( m ); - - if ( m == FL_RELEASE ) - { - sequence()->sort(); - timeline->redraw(); - } - - return r; -} diff --git a/timeline/src/Annotation_Region.H b/timeline/src/Annotation_Region.H deleted file mode 100644 index 9d56da7..0000000 --- a/timeline/src/Annotation_Region.H +++ /dev/null @@ -1,57 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -// #include "Loggable.H" -#include "Sequence_Region.H" - - -class Annotation_Region : public Sequence_Region -{ - - /* not permitted */ - Annotation_Region & operator = ( const Annotation_Region &rhs ); - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - Annotation_Region ( ) - { - } - - Annotation_Region ( const Annotation_Region &rhs ); - -public: - - /* for loggable */ - LOG_CREATE_FUNC( Annotation_Region ); - SEQUENCE_WIDGET_CLONE_FUNC( Annotation_Region ); - - Annotation_Region ( Sequence *track, nframes_t when, const char *name ); - virtual ~Annotation_Region ( ); - - void draw_box ( void ); - void draw ( void ); - int handle ( int m ); - -}; diff --git a/timeline/src/Annotation_Sequence.H b/timeline/src/Annotation_Sequence.H deleted file mode 100644 index 8c4d117..0000000 --- a/timeline/src/Annotation_Sequence.H +++ /dev/null @@ -1,156 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence.H" -#include "Annotation_Point.H" -#include "Annotation_Region.H" -#include "Timeline.H" - -#include "Track.H" - -class Annotation_Sequence : public Sequence -{ - -protected: - - virtual void get ( Log_Entry &e ) const - { - e.add( ":track", _track ); - } - - void - set ( Log_Entry &e ) - { - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( ":track", s ) ) - { - int i; - sscanf( v, "%X", &i ); - Track *t = (Track*)Loggable::find( i ); - - assert( t ); - - t->add( this ); - } - } - } - - Annotation_Sequence ( ) : Sequence ( 0 ) - { - color( FL_DARK1 ); - } - -public: - - - LOG_CREATE_FUNC( Annotation_Sequence ); - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_INSERT; } - - Annotation_Sequence ( Track *track ) : Sequence( track ) - { - color( FL_DARK1 ); - - log_create(); - } - - virtual ~Annotation_Sequence ( ) - { - Loggable::block_start(); - - clear(); - - log_destroy(); - - track()->remove( this ); - - Loggable::block_end(); - } - - int handle ( int m ) - { - - if ( Sequence::handle( m ) ) - return 1; - - switch ( m ) - { - case FL_PUSH: - { - if ( Fl::event_x() < drawable_x() ) - return 0; - - Logger log( this ); - - if ( Fl::event_button1() ) - { - new Annotation_Point( this, x_to_offset( Fl::event_x() - drawable_x() ), "mark" ); - redraw(); - } - if ( Fl::event_button3() && Fl::event_shift() ) - { - Annotation_Region *r = new Annotation_Region( this, x_to_offset( Fl::event_x() - drawable_x() ), "mark" ); - - Sequence_Widget::pushed( r ); - - r->handle( m ); - - redraw(); - - return 1; - - } - else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) ) - { - - Fl_Menu_Item menu[] = - { - { "Remove" }, - { 0 } - }; - - const Fl_Menu_Item *r = menu->popup( Fl::event_x(), Fl::event_y(), "Annotation Sequence" ); - - if ( r ) - { - if ( r == &menu[ 0 ] ) - { - Fl::delete_widget( this ); - } - - } - - return 1; - } - break; - } - default: - break; - } - - return 0; - } -}; diff --git a/timeline/src/Audio_Region.C b/timeline/src/Audio_Region.C deleted file mode 100644 index 49f4bd9..0000000 --- a/timeline/src/Audio_Region.C +++ /dev/null @@ -1,973 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include -#include -#include - -#include "Sequence.H" -#include "Audio_Region.H" -#include "Timeline.H" -#include "Waveform.H" -#include "Audio_Sequence.H" -#include "Track.H" - -#include "Engine/Audio_File.H" -#include "Transport.H" -#include "const.h" -#include "debug.h" -#include - -#include -using std::min; -using std::max; - - - -/* defined in timeline.C */ -extern void draw_full_arrow_symbol ( Fl_Color color ); - -extern Timeline *timeline; -extern Transport *transport; - -bool Audio_Region::inherit_track_color = true; -bool Audio_Region::show_box = true; - -Fl_Boxtype Audio_Region::_box = FL_BORDER_BOX; - -Fl_Color Audio_Region::_selection_color = FL_MAGENTA; - - - -/* static Fl_Color fl_invert_color ( Fl_Color c ) */ -/* { */ -/* unsigned char r, g, b; */ - -/* Fl::get_color( c, r, g, b ); */ - -/* return fl_rgb_color( 255 - r, 255 - g, 255 - b ); */ -/* } */ - - - -void -Audio_Region::get ( Log_Entry &e ) const -{ - e.add( ":source", _clip ? _clip->name() : "" ); - e.add( ":gain", _scale ); - e.add( ":fade-in-type", _fade_in.type ); - e.add( ":fade-in-duration", _fade_in.length ); - e.add( ":fade-out-type", _fade_out.type ); - e.add( ":fade-out-duration", _fade_out.length ); - - Sequence_Region::get( e ); - - e.add( ":offset", _r->offset ); - e.add( ":loop", _loop ); -} - -void -Audio_Region::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":gain" ) ) - _scale = atof( v ); - else if ( ! strcmp( s, ":fade-in-type" ) ) - _fade_in.type = (Fade::fade_type_e)atoi( v ); - else if ( ! strcmp( s, ":fade-in-duration" ) ) - _fade_in.length = atoll( v ); - else if ( ! strcmp( s, ":fade-out-type" ) ) - _fade_out.type = (Fade::fade_type_e)atoi( v ); - else if ( ! strcmp( s, ":fade-out-duration" ) ) - _fade_out.length = atoll( v ); - else if ( ! strcmp( s, ":offset" ) ) - _r->offset = atoll( v ); - else if ( ! strcmp( s, ":loop" ) ) - _loop = atoll( v ); - else if ( ! strcmp( s, ":source" ) ) - { - if ( ! ( _clip = Audio_File::from_file( v ) ) ) - { - printf( "Grave error: could not open source \"%s\"\n", v ); - } - } - } - - Sequence_Region::set( e ); -} - -void -Audio_Region::init ( void ) -{ - _adjusting_gain = 0; - _loop = 0; - _sequence = NULL; - _scale = 1.0f; - _clip = NULL; - - _color = FL_FOREGROUND_COLOR; - _box_color = FL_GRAY; - - /* FIXME: shouldn't this be a fraction of the sample rate? */ - _fade_in.length = 256; - _fade_in.type = Fade::Sigmoid; - - _fade_out = _fade_in; -} - -/* copy constructor */ -Audio_Region::Audio_Region ( const Audio_Region & rhs ) : Sequence_Region( rhs ) -{ -// *((Sequence_Region*)this) = (Sequence_Region &)rhs; - - _clip = rhs._clip->duplicate(); - _scale = rhs._scale; - - _fade_in = rhs._fade_in; - _fade_out = rhs._fade_out; - - _loop = rhs._loop; - - _box_color = rhs._box_color; - _color = rhs._color; - - _adjusting_gain = 0.0f; - - log_create(); -} - -/* */ -Audio_Region::Audio_Region ( Audio_File *c ) -{ - init(); - _clip = c; - _r->length = _clip->length(); - - log_create(); -} - -/* used when DND importing and when recording. must not invoke log_create() */ -Audio_Region::Audio_Region ( Audio_File *c, Sequence *t, nframes_t o ) -{ - init(); - _clip = c; - _r->offset = 0; - _r->start = o; - _r->length = _clip->length(); - - int sum = 0; - const char *s = rindex( _clip->name(), '/' ); - if ( ! s ) - s = _clip->name(); - - for ( int i = strlen( s ); i--; ) - sum += s[ i ]; - - while ( sum >> 8 ) - sum = (sum & 0xFF) + (sum >> 8); - - _box_color = (Fl_Color)sum; - - t->add( this ); -} - -Audio_Region::~Audio_Region ( ) -{ - log_destroy(); - - _clip->release(); -} - - - -void -Audio_Region::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Audio_Region*)v)->menu_cb( (Fl_Menu_*) w ); -} - -void -Audio_Region::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[256]; - - m->item_pathname( picked, sizeof( picked ) ); - - if ( ! strcmp( picked, "Fade/In/Linear" ) ) - _fade_in.type = Fade::Linear; - else if ( ! strcmp( picked, "Fade/In/Sigmoid" ) ) - _fade_in.type = Fade::Sigmoid; - else if ( ! strcmp( picked, "Fade/In/Logarithmic" ) ) - _fade_in.type = Fade::Logarithmic; - else if ( ! strcmp( picked, "Fade/In/Parabolic" ) ) - _fade_in.type = Fade::Parabolic; - else if ( ! strcmp( picked, "Fade/Out/Linear" ) ) - _fade_out.type = Fade::Linear; - else if ( ! strcmp( picked, "Fade/Out/Sigmoid" ) ) - _fade_out.type = Fade::Sigmoid; - else if ( ! strcmp( picked, "Fade/Out/Logarithmic" ) ) - _fade_out.type = Fade::Logarithmic; - else if ( ! strcmp( picked, "Fade/Out/Parabolic" ) ) - _fade_out.type = Fade::Parabolic; - else if ( ! strcmp( picked, "/Color" ) ) - box_color( fl_show_colormap( box_color() ) ); - else if ( ! strcmp( picked, "/Split at mouse" ) ) - { - split( timeline->x_to_offset( Fl::event_x() ) ); - } - else if ( ! strcmp( picked, "/Crop to range" ) ) - { - trim_left( timeline->range_start() ); - trim_right( timeline->range_end() ); - } - else if ( ! strcmp( picked, "/Fade in to mouse" ) ) - { - nframes_t offset = x_to_offset( Fl::event_x() ); - - if ( offset < length() ) - _fade_in.length = offset; - - DMESSAGE( "set fade in duration" ); - } - else if ( ! strcmp( picked, "/Fade out to mouse" ) ) - { - long offset = length() - x_to_offset( Fl::event_x() ); - - if ( offset > 0 ) - _fade_out.length = offset; - } - else if ( ! strcmp( picked, "/Gain with mouse vertical drag" ) ) - { - /* float g = h() / (y() - Fl::event_y() ); */ - - /* _scale = g; */ - } - else if ( ! strcmp( picked, "/Loop point to mouse" ) ) - { - nframes_t offset = x_to_offset( Fl::event_x() ); - - if ( offset > 0 ) - { - nframes_t f = offset + _r->start; - - if ( timeline->nearest_line( &f, false ) ) - _loop = f - _r->start; - else - _loop = offset; - } - } - else if ( ! strcmp( picked, "/Clear loop point" ) ) - _loop = 0; - else if ( ! strcmp( picked, "/Normalize" ) ) - normalize(); - else if ( ! strcmp( picked, "/Denormalize" ) ) - _scale = 1.0; - else if ( ! strcmp( picked, "/Range from" ) ) - timeline->range( start(), length() ); - else if ( ! strcmp( picked, "/Trim left to playhead" ) ) - { - redraw(); - trim_left( transport->frame ); - } - else if ( ! strcmp( picked, "/Trim right to playhead" ) ) - { - redraw(); - trim_right( transport->frame ); - } - else if ( ! strcmp( picked, "/Split at playhead" ) ) - { - redraw(); - - split( transport->frame ); - } - else if ( ! strcmp( picked, "/Loop point at playhead" ) ) - { - nframes_t f = transport->frame; - - _loop = f - _r->start; - } - else if ( ! strcmp( picked, "/Fade in to playhead" ) ) - { - nframes_t offset = transport->frame - _r->start; - - if ( offset < length() ) - _fade_in.length = offset; - } - else if ( ! strcmp( picked, "/Fade out to playhead" ) ) - { - nframes_t offset = _r->start + _r->length - transport->frame; - - if ( offset > 0 ) - _fade_out.length = offset; - } - else if ( ! strcmp( picked, "/Remove" ) ) - remove(); - else - FATAL( "Unknown menu choice \"%s\"", picked ); - - redraw(); -} - -#include "FL/test_press.H" -#include "FL/menu_popup.H" - -/** build the context menu for this region */ -Fl_Menu_Button & -Audio_Region::menu ( void ) -{ - static Fl_Menu_Button m( 0, 0, 0, 0, "Region" ); - - Fade::fade_type_e it = _fade_in.type; - Fade::fade_type_e ot = _fade_out.type; - - Fl_Menu_Item items[] = - { - { "Fade", 0, 0, 0, FL_SUBMENU }, - { "In", 0, 0, 0, FL_SUBMENU }, - { "Linear", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Linear ? FL_MENU_VALUE : 0 ) }, - { "Sigmoid", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Sigmoid ? FL_MENU_VALUE : 0 ) }, - { "Logarithmic", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Logarithmic ? FL_MENU_VALUE : 0 ) }, - { "Parabolic", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Parabolic ? FL_MENU_VALUE : 0 ) }, - { 0 }, - { "Out", 0, 0, 0, FL_SUBMENU }, - { "Linear", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Linear ? FL_MENU_VALUE : 0 ) }, - { "Sigmoid", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Sigmoid ? FL_MENU_VALUE : 0 ) }, - { "Logarithmic", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Logarithmic ? FL_MENU_VALUE : 0 ) }, - { "Parabolic", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Parabolic ? FL_MENU_VALUE : 0 ) }, - { 0 }, - { 0 }, - { "Color", 0, 0, 0, inherit_track_color ? FL_MENU_INACTIVE : 0 }, - { "Crop to range", 'c', 0, 0, FL_MENU_DIVIDER }, - { "Split at mouse", 's', 0, 0 }, - { "Gain with mouse vertical drag", 'g', 0, 0 }, - { "Fade in to mouse", FL_F + 3, 0, 0 }, - { "Fade out to mouse", FL_F + 4, 0, 0 }, - { "Loop point to mouse", 'l', 0, 0 }, - { "Clear loop point", 0, 0, 0, 0 == _loop ? FL_MENU_INACTIVE : 0 }, - { "Normalize", 'n', 0, 0 }, - { "Denormalize", FL_SHIFT + 'n', 0, 0, 1.0 == _scale ? FL_MENU_INACTIVE : 0 }, - { "Range from", FL_CTRL + 'r', 0, 0, FL_MENU_DIVIDER }, - { "Trim left to playhead", '{', 0, 0 }, - { "Trim right to playhead", '}', 0, 0 }, - { "Split at playhead", FL_SHIFT + 's', 0, 0 }, - { "Loop point at playhead", FL_SHIFT + 'l', 0, 0 }, - { "Fade in to playhead", FL_F + 3 + FL_SHIFT, 0, 0 }, - { "Fade out to playhead", FL_F + 4 + FL_SHIFT, 0, 0 }, - { "Remove", 0, 0, 0 }, - { 0 }, - }; - - menu_set_callback( items, &Audio_Region::menu_cb, (void*)this ); - - m.copy( items, (void*)this ); - - return m; -} - -/** Draws the curve for a single fade. /X/ and /W/ repersent the - portion of the region covered by this draw, which may or may not - cover the fade in question. */ -void -Audio_Region::draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool line, int X, int W ) -{ - const int dy = y() + Fl::box_dy( box() ); - const int dh = h() - Fl::box_dh( box() ); - const int height = dh; - const int width = timeline->ts_to_x( fade.length ); - - if ( width < 4 ) - /* too small to draw */ - return; - - int fx; - - if ( dir == Fade::In ) - { - fx = curve_x(); - - if ( fx + width < X || - fx > X + W ) - /* clipped */ - return; - } - else - { - fx = curve_x() + abs_w(); - - if ( fx - width > X + W || - fx < X ) - /* clipped */ - return; - } - - if ( line ) - fl_begin_line(); - else - fl_begin_polygon(); - - fl_vertex( fx, dy ); - fl_vertex( fx, dy + height ); - - { - const double ti = 1.0 / (double)width; - double ts = 0.0; - - const int xi = dir == Fade::In ? 1 : -1; - - for ( int i = 0; i < width; i++, ts += ti, fx += xi ) - fl_vertex( fx, dy + height - ( height * fade.gain( ts ))); - } - - fl_vertex( fx, dy ); - - if ( line ) - fl_end_line(); - else - fl_end_polygon(); -} - -Fl_Color -Audio_Region::actual_box_color ( void ) const -{ - return Audio_Region::inherit_track_color ? sequence()->track()->color() : _box_color; -} - -void -Audio_Region::draw_box( void ) -{ -// fl_push_clip( x(), y(), w(), h() ); - - Fl_Color selection_color = _selection_color; - - Fl_Color color = actual_box_color(); - - color = fl_color_average( color, sequence()->color(), 0.75f ); - - if ( recording() ) - { - color = FL_RED; - } - else if ( ! active_r() ) - { - color = fl_inactive( color ); - selection_color = fl_inactive( selection_color ); - } - - Fl_Boxtype b; - Fl_Color c = selected() ? fl_color_average( color, fl_rgb_color(10,10,10), 0.4f ) : color; - - if ( Audio_Region::show_box ) - { - b = box(); - } - else - { - b = FL_DOWN_FRAME; - } - - fl_draw_box( b, x(), y(), w(), h(), c ); - -// fl_pop_clip(); -} - -void -Audio_Region::peaks_ready_callback ( void *v ) -{ - /* this is called from the peak builder thread */ - - DMESSAGE("Damaging region from peaks ready callback"); - Fl::lock(); - ((Audio_Region*)v)->redraw(); - Fl::unlock(); - Fl::awake(); -} - -bool -Audio_Region::recording ( void ) const -{ - return this == sequence()->track()->capture_region(); -} - -/** Draw (part of) region. X, Y, W and H are the rectangle we're clipped to. */ -void -Audio_Region::draw ( void ) -{ - /* intersect clip with region */ - - int X, Y, W, H; - - fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); - - if ( ! ( W > 0 && H > 0 ) ) - /* no coverage */ - return; - - - if ( start() > timeline->xoffset + timeline->x_to_ts( sequence()->drawable_w() ) || - start() + length() < timeline->xoffset ) - /* not in viewport */ - return; - - fl_push_clip( X, Y, W, H ); - - /* overdraw a little to avoid artifacts when scrolling */ - W += 2; - -// Fl_Color c = selected() ? fl_invert_color( _color ) : _color; - - if ( sequence()->damage() & FL_DAMAGE_USER1 && - recording() ) - { - /* TODO: limit drawing. */ - } - - /* calculate waveform offset due to scrolling */ - /* offset is the number of frames into the waveform the value of X translates to */ - - /* this is the timestamp at where we'll actually be drawing. */ - nframes_t x_frame = timeline->x_to_ts( - timeline->ts_to_x( timeline->xoffset ) + ( X - _sequence->drawable_x() ) ); - - nframes_t offset = 0; - - if ( x_frame > start() ) - offset = x_frame - start(); - - nframes_t fo = 0; - nframes_t ostart = 0, oend = 0; - const int total_peaks_needed = W; - nframes_t total_frames_needed = timeline->x_to_ts( total_peaks_needed ); - - { - /* Fl_Color c = fl_color_average( FL_DARK1, */ - /* Audio_Region::inherit_track_color ? sequence()->track()->color() : _box_color, */ - /* 0.75f ); */ - - fl_color( fl_color_add_alpha( FL_DARK1, 127 ) ); - - draw_fade( _fade_in, Fade::In, false, X, W ); - draw_fade( _fade_out, Fade::Out, false, X, W ); - } - - int channels = 0; - int peaks = 0; - Peak *pbuf = NULL; - - - Fl_Color fg_color = FL_FOREGROUND_COLOR; - Fl_Color bg_color = FL_BACKGROUND_COLOR; - - if ( !active_r() ) - { - fg_color = fl_inactive(fg_color); - bg_color = fl_inactive(bg_color); - } - - do { - - nframes_t loop_frames_needed = _loop ? _loop : total_frames_needed; - int loop_peaks_needed = timeline->ts_to_x( loop_frames_needed ); - - nframes_t start = _r->offset; - - if ( ! fo ) /* first loop... */ - { - if ( _loop ) - { -// start += offset; - start += offset % _loop; - loop_frames_needed -= offset % loop_frames_needed; - loop_peaks_needed = timeline->ts_to_x( loop_frames_needed ); - } - else - start += offset; - - assert( loop_peaks_needed >= 0 ); - } - - if ( fo + loop_frames_needed > total_frames_needed ) - { - loop_frames_needed -= ( fo + loop_frames_needed ) - total_frames_needed; - loop_peaks_needed = timeline->ts_to_x( loop_frames_needed ); - } - - if ( !loop_peaks_needed ) - break; - - const nframes_t end = start + loop_frames_needed; - - if ( start != ostart || end != oend ) - { - _clip->peaks()->peakfile_ready(); - - if ( _clip->read_peaks( timeline->fpp(), - start, - end, - &peaks, &pbuf, &channels ) ) - { - Waveform::scale( pbuf, peaks * channels, _scale ); - - ostart = start; - oend = end; - } - - if ( _clip->peaks()->needs_more_peaks() && ! transport->rolling ) - { - /* maybe create a thread to make the peaks */ - /* this function will just return if there's nothing to do. */ - _clip->peaks()->make_peaks_asynchronously( Audio_Region::peaks_ready_callback, this ); - } - } - else - { -// DMESSAGE( "using cached peaks" ); - } - - if ( peaks && pbuf ) - { - int ch = (h() - Fl::box_dh( box() )) / channels; - int xo = timeline->ts_to_x( fo ); - - for ( int i = 0; i < channels; ++i ) - { - Waveform::draw( X + xo, - (y() + Fl::box_dy( box() )) + (i * ch), - loop_peaks_needed, - ch, - pbuf + i, peaks, channels, - fg_color, bg_color ); - } - } - else - ; -// WARNING( "Pbuf == %p, peaks = %lu", pbuf, (unsigned long)peaks ); - - - - if ( _loop ) - { - const int lx = sequence()->drawable_x() + timeline->ts_to_x( ( this->start() + _loop ) - timeline->xoffset ); - - if ( lx < X + W ) - { - fl_color( fl_darker( FL_CYAN ) ); - fl_line( lx, y(), lx, y() + h() ); - fl_line( lx - 3, y(), lx + 3, y() ); - fl_line( lx - 3, y() + h() - 1, lx + 3, y() + h() - 1 ); - - } - } - - if ( peaks < loop_peaks_needed ) - { -// DMESSAGE( "Peak read came up %lu peaks short", (unsigned long)loop_peaks_needed - peaks ); - } - - fo += loop_frames_needed; - - } - while ( _loop && fo < total_frames_needed ); - - - - if ( _adjusting_gain > 0.0f ) - { - fl_color( fl_color_add_alpha( FL_DARK1, 127 ) ); - - fl_rectf( X, ( y() + h() ) - ( h() * ( _scale * 0.25 ) ), X + W, y() + h() ); - - fl_line_style( FL_DASH, 1 ); - - fl_color( fl_color_add_alpha( FL_GREEN, 200 ) ); - - float j = 5; - - for ( int i = y() + h(); i > y(); i -= j, j *= 1.2 ) - { - fl_line( X, i, X + W, i ); - } - - fl_line_style( FL_SOLID, 0 ); - } - - if ( selected() ) - draw_selection_frame( line_x() + Fl::box_dx(box()), - y() + Fl::box_dy(box()), - abs_w() - Fl::box_dw(box()), - h() - Fl::box_dh(box()), - selection_color() ); - -/* if ( current() ) */ -/* { */ -/* /\* draw length bubble *\/ */ - -/* char pat[40]; */ - -/* snprintf( pat, sizeof( pat ), "%dm:%.1fs", (int)(length() / timeline->sample_rate()) / 60, (double)length() / timeline->sample_rate() ); */ - -/* draw_label( pat, (Fl_Align)(FL_ALIGN_INSIDE | FL_ALIGN_CENTER), FL_GREEN ); */ -/* } */ - - fl_pop_clip(); - -} - -void -Audio_Region::draw_label ( void ) -{ - if ( _clip->dummy() ) - { - char pat[256]; - snprintf( pat, sizeof( pat ), "Missing Source!: %s", _clip->name() ); - draw_label( pat, align() ); - } - else - draw_label( _clip->name(), align() ); -} - -/** split region at absolute frame /where/ */ -void -Audio_Region::split ( nframes_t where ) -{ - block_start(); - - nframes_t old_fade_in = _fade_in.length; - - _fade_in.length = 256; - - Audio_Region *copy = new Audio_Region( *this ); - - { - Logger _log( copy ); - - _fade_in.length = old_fade_in; - _fade_out.length = 256; - - Sequence_Region::split( copy, where ); - } - - log_end(); - - block_end(); - - log_start(); -} - -int -Audio_Region::handle ( int m ) -{ - static int ox; - - static bool copied = false; - static nframes_t os; - - int X = Fl::event_x(); - int Y = Fl::event_y(); - - Logger _log( this ); - - if ( ! Fl::pushed() ) - // selecting an item from the context menu can leave this value set. - Sequence_Widget::pushed( NULL ); - - switch ( m ) - { - case FL_FOCUS: - case FL_UNFOCUS: - return 1; - case FL_KEYUP: - if ( _adjusting_gain > 0 ) - { - _adjusting_gain = 0; - redraw(); - return 1; - } - break; - case FL_KEYBOARD: - if ( Fl::event_key() == 'g' ) - { - if ( _adjusting_gain <= 0 ) - { - _adjusting_gain = _scale; - redraw(); - } - return 1; - } - return menu().test_shortcut() != 0; - case FL_ENTER: - return Sequence_Region::handle( m ); - case FL_LEAVE: - if ( _adjusting_gain > 0 ) - { - _adjusting_gain = 0; - redraw(); - } - return Sequence_Region::handle( m ); - case FL_PUSH: - { - if ( _adjusting_gain > 0.0f ) - { - _adjusting_gain = _scale; - return 1; - } - - /* splitting */ - if ( test_press( FL_BUTTON2 | FL_SHIFT ) ) - { - /* split */ - if ( ! copied ) - { - split( timeline->x_to_offset( X ) ); - } - - return 0; - } - else - { - ox = x() - X; - /* for panning */ - os = _r->offset; - - if ( test_press( FL_BUTTON2 | FL_CTRL ) ) - { - normalize(); - return 1; - } - else if ( test_press( FL_BUTTON3 ) ) - { - /* context menu */ - menu_popup( &menu() ); - - return 1; - } - else - return Sequence_Region::handle( m ); - } - - break; - } - case FL_RELEASE: - { - Sequence_Region::handle( m ); - - copied = false; - - return 1; - } - case FL_DRAG: - - if ( Fl::event_is_click() ) - return 1; - - if ( ! _drag ) - { - begin_drag( Drag( X, Y, x_to_offset( X ) ) ); - _log.hold(); - } - - if ( _adjusting_gain ) - { - int d = _drag->y - Y; - - _scale = _adjusting_gain + ( 0.01f * d ); - - if ( _scale < 0.01f ) - _scale = 0.01f; - - redraw(); - return 1; - } - - if ( test_press( FL_BUTTON1 | FL_SHIFT | FL_CTRL ) ) - { - /* panning */ - int d = (ox + X) - x(); - - if ( d < 0 ) - _r->offset = os + timeline->x_to_ts( 0 - d ); - else - { - if ( os < timeline->x_to_ts( d ) ) - _r->offset = 0; - else - _r->offset = os - timeline->x_to_ts( d ); - } - - redraw(); - return 1; - } - - return Sequence_Region::handle( m ); - - default: - return Sequence_Region::handle( m ); - break; - } - - return 0; -} - - - -/**********/ -/* Public */ -/**********/ - -/** return the name of the audio source this region represents */ -const char * -Audio_Region::source_name ( void ) const -{ - return _clip->name(); -} - -/** set the amplitude scaling for this region from the normalization - * factor for the range of samples represented by this region */ -void -Audio_Region::normalize ( void ) -{ - int peaks, channels; - Peak *pbuf; - - const nframes_t npeaks = _loop ? _loop : length(); - - - if ( _clip->read_peaks( npeaks, offset(), offset() + npeaks, &peaks, &pbuf, &channels ) && - peaks ) - { - _scale = 1000.0f; - - for ( int i = 0; i < channels; i++ ) - { - float f = (pbuf + i)->normalization_factor(); - if ( f < _scale ) - _scale = f; - } - } - - /* FIXME: wrong place for this? */ - sequence()->handle_widget_change( start(), length() ); - redraw(); -} diff --git a/timeline/src/Audio_Region.H b/timeline/src/Audio_Region.H deleted file mode 100644 index fb142d8..0000000 --- a/timeline/src/Audio_Region.H +++ /dev/null @@ -1,176 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Timeline.H" -#include "Sequence_Region.H" - -class Audio_File; - -class Fl_Menu_; -class Fl_Menu_Button; - -class Audio_Region : public Sequence_Region -{ - - /* not permitted */ - Audio_Region & operator = ( const Audio_Region &rhs ); - - static void peaks_ready_callback ( void *v ); - -public: - - static bool inherit_track_color; - static bool show_box; - - struct Fade - { - enum fade_type_e { Linear = 0, Sigmoid, Logarithmic, Parabolic }; - enum fade_dir_e { In, Out }; - - fade_type_e type; - nframes_t length; - - Fade ( ) - { - type = Linear; - length = 0; - } - - bool - operator< ( const Fade &rhs ) const - { - return length < rhs.length; - } - - double increment ( void ) const - { - return 1.0f / length; - } - - /** Return gain for frame /index/ of /nframes/ on a gain curve - * of type /type/.*/ - /* FIXME: calling a function per sample is bad, switching on - * type mid fade is bad. */ - inline float - gain ( const float fi ) const - { - switch ( type ) - { - case Linear: - return fi; - case Sigmoid: - return (1.0f - cosf( fi * M_PI )) * 0.5f; - case Logarithmic: - return powf( 0.1f, (1.0f - fi) * 3.0f ); - case Parabolic: - return 1.0f - (1.0f - fi) * (1.0f - fi); - default: - return 1.0f; - } - } - - void apply ( sample_t *buf, fade_dir_e dir, nframes_t start, nframes_t nframes ) const; - void apply_interleaved ( sample_t *buf, fade_dir_e dir, nframes_t start, nframes_t nframes, int channels ) const; - - }; - -/* struct Fade_In : public Fade; */ -/* struct Fade_Out : public Fade; */ - -private: - - Audio_File *_clip; /* clip this region represents */ - - float _adjusting_gain; - float _scale; /* amplitude adjustment */ - - Fade _fade_in; - Fade _fade_out; - - nframes_t _loop; /* loop point */ - - friend class Track; /* for _clip */ - - Fl_Menu_Button & menu ( void ); - - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( const Fl_Menu_ *m ); - - void draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool filled, int X, int W ); - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - virtual void draw_label ( const char *label, Fl_Align align, Fl_Color color=(Fl_Color)0, int xo=0, int yo=0 ) - { - Sequence_Widget::draw_label( label, align ); - } - virtual void draw_label ( void ); - - int handle ( int m ); - void draw_box ( void ); - void draw ( void ); - void resize ( void ); - -public: - - LOG_CREATE_FUNC( Audio_Region ); - - SEQUENCE_WIDGET_CLONE_FUNC( Audio_Region ); - - static Fl_Boxtype _box; - static Fl_Color _selection_color; - Fl_Color selection_color ( void ) const { return _selection_color; } - void selection_color ( Fl_Color v ) { _selection_color = v; } - - void init ( void ); - - Audio_Region ( ) - { - init(); - } - - bool current ( void ) const { return this == belowmouse(); } - - const char * source_name ( void ) const; - - Audio_Region ( const Audio_Region & rhs ); - Audio_Region ( Audio_File *c ); - Audio_Region ( Audio_File *c, Sequence *t, nframes_t o ); - ~Audio_Region ( ); - - Fl_Boxtype box ( void ) const { return Audio_Region::_box; } - Fl_Align align ( void ) const { return (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_BOTTOM | FL_ALIGN_INSIDE | FL_ALIGN_CLIP ); } - - void normalize ( void ); - void split ( nframes_t where ); - bool recording ( void ) const; - - virtual Fl_Color actual_box_color ( void ) const; - /* Engine */ - nframes_t read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t nframes, int out_channels ) const; - nframes_t write ( nframes_t nframes ); - void prepare ( void ); - bool finalize ( nframes_t frame ); - -}; diff --git a/timeline/src/Audio_Sequence.C b/timeline/src/Audio_Sequence.C deleted file mode 100644 index f8dddd5..0000000 --- a/timeline/src/Audio_Sequence.C +++ /dev/null @@ -1,366 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* An Audio_Sequence is a sequence of Audio_Regions. Takes and 'track - * contents' consist of these objects */ - -#include "debug.h" - -#include -#include -#include -#include "Audio_Sequence.H" -#include "Waveform.H" - -#include -using namespace std; - -#include "Track.H" - -#include "Engine/Audio_File.H" // for ::from_file() -#include "Transport.H" // for locate() -#include "Track_Header.H" -#include - -#include // for symlink() - -#include "string_util.h" - - - -const char * -Audio_Sequence::name ( void ) const -{ - return Sequence::name(); -} - -void -Audio_Sequence::name ( const char *s ) -{ - Sequence::name( s ); - header()->name_input->value( s ); -} - -void -Audio_Sequence::cb_button ( Fl_Widget *w, void *v ) -{ - ((Audio_Sequence*)v)->cb_button( w ); -} - -void -Audio_Sequence::cb_button ( Fl_Widget *w ) -{ - Logger log(this); - - if ( w == header()->name_input ) - { - Sequence::name( header()->name_input->value() ); - } - else if ( w == header()->delete_button ) - { - track()->remove( this ); - } - else if ( w == header()->promote_button ) - { - track()->sequence( this ); - } -} - -void -Audio_Sequence::init ( void ) -{ - labeltype( FL_NO_LABEL ); - { - Audio_Sequence_Header *o = new Audio_Sequence_Header( x(), y(), Track::width(), 52 ); - - o->name_input->callback( cb_button, this ); - o->delete_button->callback( cb_button, this ); - o->promote_button->callback( cb_button, this ); - - Fl_Group::add( o ); - } - - resizable(0); -} - -Audio_Sequence::Audio_Sequence ( Track *track, const char *name ) : Sequence( track ) -{ - _track = track; - - init(); - - if ( name ) - Audio_Sequence::name( name ); - else - { - struct timeval tv; - - gettimeofday( &tv, NULL ); - - time_t t = tv.tv_sec; - - char s[40]; - - ctime_r( &t, s ); - - s[ strlen( s ) - 1 ] = 0; - - Audio_Sequence::name( s ); - } - - if ( track ) - track->add( this ); - - log_create(); -} - - -Audio_Sequence::~Audio_Sequence ( ) -{ - Loggable::block_start(); - - clear(); - - log_destroy(); - - track()->remove( this ); - - Loggable::block_end(); -} - - - -/** return a pointer to the current capture region for this sequence */ -const Audio_Region * -Audio_Sequence::capture_region ( void ) const -{ - return track()->capture_region(); -} - -void -Audio_Sequence::get ( Log_Entry &e ) const -{ - e.add( ":track", _track ); - e.add( ":name", name() ); -} - -void -Audio_Sequence::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( ":track", s ) ) - { - int i; - sscanf( v, "%X", &i ); - Track *t = (Track*)Loggable::find( i ); - - assert( t ); - - t->sequence( this ); - } - else if ( ! strcmp( ":name", s ) ) - name( v ); - } -} - - -void -Audio_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) -{ - Sequence::handle_widget_change( start, length ); - - /* a region has changed. we may need to rebuffer... */ - - /* trigger rebuffer */ - /* FIXME: we really only need to rebuffer *this* sequence! */ - /* FIXME: how does this fit into the selection? */ - - if ( transport->rolling && ( start > transport->frame || start + length > transport->frame ) ) - transport->locate( transport->frame ); -} - -void -Audio_Sequence::draw ( void ) -{ - - Sequence::draw(); - - int xfades = 0; - - fl_push_clip( drawable_x(), y(), drawable_w(), h() ); - - /* draw crossfades */ - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) - { - Sequence_Widget *o = overlaps( *r ); - - if ( o ) - { - if ( *o <= **r ) - { -/* if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */ -/* printf( "complete superposition\n" ); */ - - if ( o->contains( *r ) ) - /* completely inside */ - continue; - - ++xfades; - - Rectangle b( (*r)->x(), - o->y(), - (o->x() + o->w()) - (*r)->x(), - o->h() ); - - if ( b.w > 0 ) - { - cairo_t *cc = Fl::cairo_cc(); - - cairo_set_operator( cc, CAIRO_OPERATOR_HSL_COLOR ); - cairo_set_source_rgba( cc, 1, 1, 0, 0.80 ); - cairo_rectangle( cc, b.x, b.y, b.w, b.h ); - - cairo_fill( cc ); - - cairo_set_operator( cc, CAIRO_OPERATOR_OVER ); - } - } - } - - } - - fl_pop_clip(); -} - -int -Audio_Sequence::handle_paste ( const char *text ) -{ - int X = Fl::event_x(); - - if ( ! strcmp( text, "Audio_Region" ) ) - return 1; - - char *file; - - if ( ! sscanf( text, "file://%m[^\r\n]\n", &file ) ) - { - WARNING( "invalid drop \"%s\"\n", text ); - return 0; - } - - unescape_url( file ); - - printf( "pasted file \"%s\"\n", file ); - - fl_cursor( FL_CURSOR_WAIT ); - Fl::check(); - - char *t = strdup( file ); - - char *filebase = strdup( basename( t ) ); - - free( t ); - - char *s = 0; - - int i = 0; - - for ( ; ; i++ ) - { - if ( i ) - { - free( s ); - asprintf( &s, "sources/%s-%i", filebase, i ); - } - else - asprintf( &s, "sources/%s", filebase ); - - DMESSAGE( "Symlink %s -> %s", file, s ); - if ( symlink( file, s ) == 0 ) - break; - - if ( errno != EEXIST ) - { - WARNING( "Failed to create symlink: %s", strerror( errno ) ); - break; - } - } - - Audio_File *c = Audio_File::from_file( basename( s ) ); - - free( s ); - free( filebase ); - - fl_cursor( FL_CURSOR_DEFAULT ); - Fl::check(); - - if ( ! c || c->dummy() ) - { - fl_alert( "Could not import file \"%s\"", file ); - free( file ); - - if ( c ) - { - delete c; - c = NULL; - } - - return 0; - } - - free( file ); - - Audio_Region *r = - new Audio_Region( c, this, timeline->xoffset + timeline->x_to_ts( X - drawable_x() ) ); - - r->log_create(); - - redraw(); - - return 1; - -} - -/** event handler that supports DND of audio clips */ -int -Audio_Sequence::handle ( int m ) -{ - switch ( m ) - { - case FL_PASTE: - { - DMESSAGE("Got sequence paste"); - - if ( ! Fl::event_inside( this ) ) - { - DMESSAGE("ignoring"); - return 0; - } - - return handle_paste(Fl::event_text()); - } - default: - return Sequence::handle( m ); - } -} diff --git a/timeline/src/Audio_Sequence.H b/timeline/src/Audio_Sequence.H deleted file mode 100644 index 756144a..0000000 --- a/timeline/src/Audio_Sequence.H +++ /dev/null @@ -1,88 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence.H" -#include "Audio_Region.H" - -#include -class Audio_Sequence_Header; - -class Audio_Sequence : public Sequence -{ - -protected: - - void get ( Log_Entry &e ) const; - - void set ( Log_Entry &e ); - - Audio_Sequence ( ) : Sequence( 0 ) - { - init(); - } - - void handle_widget_change ( nframes_t start, nframes_t length ); - - void draw ( void ); - - static void cb_button ( Fl_Widget *w, void *v ); - void cb_button ( Fl_Widget *w ); - - void init ( void ); - -public: - - int handle_paste ( const char *text ); - - int handle ( int m ); - - LOG_CREATE_FUNC( Audio_Sequence ); - - Audio_Sequence_Header * header ( void ) { return (Audio_Sequence_Header*)child(0); } - - Audio_Sequence ( Track *track, const char *name = 0 ); - ~Audio_Sequence ( ); - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - - virtual Sequence * clone_empty ( void ) - { - Audio_Sequence *t = new Audio_Sequence( track() ); - - return t; - } - - virtual Sequence * clone_empty ( const char *name ) - { - Audio_Sequence *t = new Audio_Sequence( track(), name ); - - return t; - } - - virtual void name ( const char *s ); - virtual const char *name ( void ) const; - - const Audio_Region *capture_region ( void ) const; - - nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ); - -}; diff --git a/timeline/src/Clock.H b/timeline/src/Clock.H deleted file mode 100644 index 948b4c9..0000000 --- a/timeline/src/Clock.H +++ /dev/null @@ -1,243 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -/* Digital clock widget to show points on the timeline. May be -switched between Bar Beat Tick and Wallclock displays */ - -#include -#include -#include - -#include "Timeline.H" -#include "types.h" - -const float CLOCK_UPDATE_FREQ = 0.08f; - -/* TODO: frames per second? */ - -#include "Sequence_Widget.H" - -class Clock : public Fl_Widget -{ - /* not permitted */ - Clock ( const Clock &rhs ); - Clock & operator = ( const Clock &rhs ); - - nframes_t _when; - nframes_t *_v; - - static void - update_cb ( void *v ) - { - ((Clock*)v)->update_cb(); - } - - void - update_cb ( void ) - { - Fl::repeat_timeout( CLOCK_UPDATE_FREQ, update_cb, this ); - - set( *_v ); - } - - -public: - - enum { HMS = 0, BBT, Timecode, Sample, TYPE_MAX }; - - static void - frame_to_Timecode ( char *dst, int n, nframes_t frame ) - { - float S = (double)frame / timeline->sample_rate(); - - int M = S / 60; S -= M * 60; - int H = M / 60; M -= H * 60; - int HS = ((int)(S * 100)) - (((int)S) * 100); - - snprintf( dst, n, "%02d:%02d:%02.0f:%02d", H, M, S, HS ); - } - - static void - frame_to_HMS ( char *dst, int n, nframes_t frame ) - { - float S = (double)frame / timeline->sample_rate(); - - int M = S / 60; S -= M * 60; - int H = M / 60; M -= H * 60; - - snprintf( dst, n, "%02d:%02d:%06.3f", H, M, S ); - } - - static void - frame_to_Sample ( char *dst, int n, nframes_t frame ) - { - snprintf( dst, n, "%lu", (unsigned long)frame ); - } - - static void - frame_to_BBT ( char *dst, int n, nframes_t frame ) - { - struct BBT bbt = timeline->solve_tempomap( frame ).bbt; - - snprintf( dst, n, "%03d|%1d|%04d", bbt.bar + 1, bbt.beat + 1, bbt.tick ); - } - - - - Clock ( int X, int Y, int W, int H, const char *L=0 ) - : Fl_Widget( X, Y, W, H, L ) - { - _when = 0; - _v = 0; - box( FL_BORDER_BOX ); - type( HMS ); - - /* force size */ - size( 170, 40 ); - } - - ~Clock ( ) - { - Fl::remove_timeout( update_cb, this ); - } - - void run ( nframes_t *v ) - { - _v = v; - - Fl::add_timeout( CLOCK_UPDATE_FREQ, update_cb, this ); - } - - void set ( nframes_t frame ) - { - if ( _when != frame ) - { - _when = frame; - redraw(); - } - } - - void draw ( void ) - { - draw_box(); - - fl_push_clip( x(), y(), w(), h() ); - - char buf[15]; - *buf = '\0'; - - switch ( type() ) - { - case HMS: - frame_to_HMS( buf, sizeof( buf ), _when ); - break; - case BBT: - frame_to_BBT( buf, sizeof( buf ), _when ); - break; - case Timecode: - frame_to_Timecode( buf, sizeof( buf ), _when ); - break; - case Sample: - frame_to_Sample( buf, sizeof( buf ), _when ); - break; - default: - printf( "error: invalid clock type\n" ); - } - - - fl_font( FL_COURIER_BOLD, 24 ); - - Fl_Color c = fl_color_average( FL_WHITE, FL_GRAY, 0.60 ); - - fl_color( c ); - - const int dx = x() + Fl::box_dx( box() ); - const int dy = y() + Fl::box_dy( box() ); - const int dw = w() - Fl::box_dw( box() ); - const int dh = h() - Fl::box_dh( box() ); - - fl_draw( buf, dx, dy, dw, dh - 9, FL_ALIGN_CENTER ); - - for ( int i = strlen( buf ); i--; ) - if ( isdigit( buf[ i ] ) ) - buf[ i ] = ' '; - - fl_color( fl_darker( c ) ); - fl_draw( buf, dx, dy, dw, dh - 9, FL_ALIGN_CENTER ); - - fl_font( FL_HELVETICA, 9 ); - - const char *types[] = { "HMS", "BBT", "Timecode", "Sample" }; - - fl_color( fl_color_average( FL_WHITE, FL_GRAY, 0.50 ) ); - - switch ( type() ) - { - case Timecode: - snprintf( buf, sizeof( buf ), "%.1f", 30.0 ); - fl_draw( buf, dx, dy, dw, dh, FL_ALIGN_BOTTOM ); - break; - case Sample: - snprintf( buf, sizeof( buf ), "%lu", (unsigned long)timeline->sample_rate() ); - fl_draw( buf, dx, dy, dw, dh, FL_ALIGN_BOTTOM ); - break; - case BBT: - { - /* FIXME: find a way to avoid doing this twice */ - position_info pos = timeline->solve_tempomap( _when ); - snprintf( buf, sizeof( buf ), "%d/%d %5.1f", pos.beats_per_bar, pos.beat_type, pos.tempo ); - fl_draw( buf, dx, dy, dw, dh, FL_ALIGN_BOTTOM ); - } - default: - break; - } - - const char *s = types[ type() ]; - - fl_color( FL_RED ); - - fl_draw( s, dx + 4, dy, dw, dh, (Fl_Align)( FL_ALIGN_LEFT | FL_ALIGN_BOTTOM ) ); - - if ( label() ) - fl_draw( label(), dx, dy, dw, dh, (Fl_Align)( FL_ALIGN_RIGHT | FL_ALIGN_BOTTOM ) ); - - fl_pop_clip(); - } - - - int handle ( int m ) - { - if ( m == FL_PUSH ) - { - int t = type() + 1; - - if ( t >= TYPE_MAX ) - t = 0; - - type( t ); - - redraw(); - - return 0; - } - - return 0; - } -}; diff --git a/timeline/src/Control_Point.C b/timeline/src/Control_Point.C deleted file mode 100644 index c13f413..0000000 --- a/timeline/src/Control_Point.C +++ /dev/null @@ -1,135 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -#include "Control_Point.H" - - - -Control_Point::Control_Point ( Sequence *t, nframes_t when, float y ) -{ - _sequence = NULL; - _y = y; - _r->start = when; - _box_color = FL_WHITE; - - t->add( this ); - - log_create(); -} - -Control_Point::Control_Point ( const Control_Point &rhs ) : Sequence_Point( rhs ) -{ - _y = rhs._y; - - log_create(); -} - -void -Control_Point::get ( Log_Entry &e ) const -{ - Sequence_Point::get( e ); - - e.add( ":y", _y ); -} - -void -Control_Point::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":y" ) ) - _y = atof( v ); - - redraw(); - - // _make_label(); - } - - Sequence_Point::set( e ); -} - -void -Control_Point::draw_box ( void ) -{ - if ( selected() ) - fl_color( selection_color() ); - else - fl_color( box_color() ); - - fl_pie( x() - ( abs_w() / 2 ), y() - ( h() / 2 ), abs_w(), h(), 0, 360 ); - - if ( this == Sequence_Widget::belowmouse() || - this == Sequence_Widget::pushed() ) - { - char val[10]; - snprintf( val, sizeof( val ), "%+.2f", 1.0 - _y * 2 ); - - Fl_Align a = 0; - - if ( x() < _sequence->x() + ( _sequence->w() / 2 ) ) - a |= FL_ALIGN_RIGHT; - else - a |= FL_ALIGN_LEFT; - - if ( y() < _sequence->y() + ( _sequence->h() / 2 ) ) - a |= FL_ALIGN_BOTTOM; - else - a |= FL_ALIGN_TOP; - - draw_label( val, a, FL_FOREGROUND_COLOR ); - } -} - - -int -Control_Point::handle ( int m ) -{ - int r = Sequence_Widget::handle( m ); - - switch ( m ) - { - case FL_RELEASE: - redraw(); - break; - case FL_DRAG: - { - if ( nselected() > 1 ) - // only allow horizontal movement when part of a selection... - break; - - int Y = Fl::event_y() - parent()->y(); - - if ( Y >= 0 && Y < parent()->h() ) - { - _y = (float)Y / parent()->h(); - redraw(); - } - - break; - } - } - - return r; -} diff --git a/timeline/src/Control_Point.H b/timeline/src/Control_Point.H deleted file mode 100644 index 171be96..0000000 --- a/timeline/src/Control_Point.H +++ /dev/null @@ -1,68 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence_Point.H" - -class Control_Point : public Sequence_Point -{ - float _y; - -protected: - - Control_Point ( ) - { - _box_color = FL_WHITE; - } - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - Control_Point ( const Control_Point &rhs ); - -public: - - - /* for loggable */ - LOG_CREATE_FUNC( Control_Point ); - SEQUENCE_WIDGET_CLONE_FUNC( Control_Point ); - - Control_Point ( Sequence *t, nframes_t when, float y ); - - ~Control_Point ( ) - { - log_destroy(); - } - - float control ( void ) const { return _y; } - void control ( float v ) { _y = v; } - /* only for playback thread */ - nframes_t when ( void ) const { return _range.start; } - - long abs_w ( void ) const { return 8; } - - int y ( void ) const { return parent()->y() + ((float)parent()->h() * _y); } - int h ( void ) const { return 8; } - - virtual void draw_box ( void ); - virtual int handle ( int m ); - -}; diff --git a/timeline/src/Control_Sequence.C b/timeline/src/Control_Sequence.C deleted file mode 100644 index 503052e..0000000 --- a/timeline/src/Control_Sequence.C +++ /dev/null @@ -1,809 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" -#include "debug.h" - -#include -#include - -#include "Control_Sequence.H" -#include "Track.H" - -#include "Engine/Engine.H" // for lock() - -#include "Track_Header.H" - -#include -using std::list; - -#include "Transport.H" - -#include "OSC/Endpoint.H" - -#include "string_util.h" - -#include "FL/event_name.H" -#include "FL/test_press.H" -#include -#include "FL/menu_popup.H" - - - -#define DAMAGE_SEQUENCE FL_DAMAGE_USER1 -#define DAMAGE_HEADER FL_DAMAGE_USER2 - -bool Control_Sequence::draw_with_grid = true; -bool Control_Sequence::draw_with_polygon = true; -Fl_Widget * Control_Sequence::_highlighted = 0; - -Control_Sequence::Control_Sequence ( ) : Sequence( 0 ) -{ - init(); -} - - - -Control_Sequence::Control_Sequence ( Track *track, const char *name ) : Sequence( 0 ) -{ - init(); - - _track = track; - - this->name( name ); - - mode( OSC ); - - if ( track ) - track->add( this ); - - log_create(); -} - - -Control_Sequence::~Control_Sequence ( ) -{ - Loggable::block_start(); - - clear(); - - log_destroy(); - - track()->remove( this ); - - if ( _output ) - { - _output->shutdown(); - - delete _output; - - _output = NULL; - } - - if ( _osc_output() ) - { - OSC::Signal *t = _osc_output(); - - _osc_output( NULL ); - - delete t; - } - - for ( list::iterator i = _persistent_osc_connections.begin(); - i != _persistent_osc_connections.end(); - ++i ) - { - free( *i ); - } - - _persistent_osc_connections.clear(); - - Loggable::block_end(); -} - -const char * -Control_Sequence::name ( void ) const -{ - return Sequence::name(); -} - -void -Control_Sequence::name ( const char *s ) -{ - char *n = track()->get_unique_control_name( s ); - - Sequence::name( n ); - header()->name_input->value( n ); - - if ( mode() == CV ) - update_port_name(); - else - update_osc_path(); - - redraw(); -} - -void -Control_Sequence::update_osc_path ( void ) -{ - char *path; - asprintf( &path, "/track/%s/%s", track()->name(), name() ); - - char *s = escape_url( path ); - - free( path ); - - path = s; - - if ( !_osc_output() ) - { - OSC::Signal *t = timeline->osc->add_signal( path, OSC::Signal::Output, 0, 1, 0, NULL, NULL ); - - _osc_output( t ); - } - else - { - _osc_output()->rename( path ); - } - - free(path); -} - -void -Control_Sequence::update_port_name ( void ) -{ - bool needs_activation = false; - - char s[512]; - snprintf( s, sizeof(s), "%s-cv", name() ); - - if ( ! _output ) - { - _output = new JACK::Port( engine, track()->name(), s, JACK::Port::Output, JACK::Port::CV ); - _output->terminal( true ); - needs_activation = true; - } - - if ( name() ) - { - _output->trackname( track()->name() ); - _output->name( s ); - _output->rename(); - } - - if ( needs_activation ) - { - if ( ! _output->activate() ) - { - fl_alert( "Could not create JACK port for control output on track \"%s\"", track()->name() ); - delete _output; - _output = NULL; - } - } -} - -void -Control_Sequence::cb_button ( Fl_Widget *w, void *v ) -{ - ((Control_Sequence*)v)->cb_button( w ); -} - -void -Control_Sequence::cb_button ( Fl_Widget *w ) -{ - Logger log(this); - - if ( w == header()->name_input ) - { - name( header()->name_input->value() ); - } - else if ( w == header()->delete_button ) - { - Fl::delete_widget( this ); - } - else if ( w == header()->menu_button ) - { - menu_popup( &menu(), header()->menu_button->x(), header()->menu_button->y() ); - } - /* else if ( w == header()->promote_button ) */ - /* { */ - /* track()->sequence( this ); */ - /* } */ -} - -void -Control_Sequence::init ( void ) -{ - timeline->osc->peer_signal_notification_callback( &Control_Sequence::peer_callback, NULL ); - - labeltype( FL_NO_LABEL ); - { - Control_Sequence_Header *o = new Control_Sequence_Header( x(), y(), Track::width(), 52 ); - - o->name_input->callback( cb_button, this ); - o->delete_button->callback( cb_button, this ); - o->menu_button->callback( cb_button, this ); - /* o->promote_button->callback( cb_button, this ); */ - Fl_Group::add( o ); - } - resizable(0); - - box( FL_NO_BOX ); - - _track = NULL; - _output = NULL; - __osc_output = NULL; - _mode = (Mode)-1; - - interpolation( Linear ); -} - - - -void -Control_Sequence::get ( Log_Entry &e ) const -{ - e.add( ":track", _track ); - e.add( ":name", name() ); - e.add( ":color", color() ); -} - -void -Control_Sequence::get_unjournaled ( Log_Entry &e ) const -{ - e.add( ":interpolation", _interpolation ); - - /* if ( _osc_output() && _osc_output()->connected() ) */ - /* { */ - /* DMESSAGE( "OSC Output connections: %i", _osc_output()->noutput_connections() ); */ - - /* for ( int i = 0; i < _osc_output()->noutput_connections(); ++i ) */ - /* { */ - /* char *s; */ - - /* s = _osc_output()->get_output_connection_peer_name_and_path(i); */ - - /* e.add( ":osc-output", s ); */ - - /* free( s ); */ - /* } */ - /* } */ - - e.add( ":mode", mode() ); -} - -void -Control_Sequence::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( ":track", s ) ) - { - int i; - sscanf( v, "%X", &i ); - Track *t = (Track*)Loggable::find( i ); - - assert( t ); - - t->add( this ); - } - else if ( ! strcmp( ":name", s ) ) - { - name( v ); - } - else if ( ! strcmp( ":interpolation", s ) ) - { - interpolation( (Curve_Type)atoi( v ) ); - } - else if ( ! strcmp( ":mode", s ) ) - mode( (Mode)atoi( v ) ); - else if ( ! strcmp( ":osc-output", s ) ) - { - _persistent_osc_connections.push_back( strdup( v ) ); - } - else if ( ! strcmp( ":color", s ) ) - { - color( (Fl_Color)atol( v ) ); - } - } -} - -void -Control_Sequence::mode ( Mode m ) -{ - if ( CV != m && mode() == CV ) - { - if ( _output ) - { - _output->shutdown(); - - JACK::Port *t = _output; - - _output = NULL; - - delete t; - } - } - else if ( OSC != m && mode() == OSC ) - { - if ( _osc_output() ) - { - OSC::Signal *t = _osc_output(); - - _osc_output( NULL ); - - delete t; - } - } - - if ( CV == m && mode() != CV ) - { - update_port_name(); - - header()->outputs_indicator->label( "cv" ); - } - else if ( OSC == m && mode() != OSC ) - { - update_osc_path(); - - header()->outputs_indicator->label( "osc" ); - } - - _mode = m; -} - -void -Control_Sequence::draw_curve ( bool filled ) -{ - const int bx = drawable_x(); - const int by = y() + Fl::box_dy( box() ); - const int bw = drawable_w(); - const int bh = h() - Fl::box_dh( box() ); - - /* make a copy of the list for drawing and sort it... */ - list wl; - - std::copy( _widgets.begin(), _widgets.end(), std::back_inserter( wl ) ); - -//= new list (_widgets); - - wl.sort( Sequence_Widget::sort_func ); - - list ::const_iterator e = wl.end(); - e--; - - if ( wl.size() ) - for ( list ::const_iterator r = wl.begin(); ; r++ ) - { - const int ry = (*r)->y(); - const long rx = (*r)->curve_x(); - - if ( r == wl.begin() ) - { - if ( filled ) - fl_vertex( bx, bh + by ); - fl_vertex( bx, ry ); - } - - fl_vertex( rx, ry ); - - if ( r == e ) - { - fl_vertex( bx + bw, ry ); - if ( filled ) - fl_vertex( bx + bw, bh + by ); - break; - } - - } -} - -void -Control_Sequence::draw_box ( void ) -{ - const int bx = drawable_x(); - const int by = y(); - const int bw = drawable_w(); - const int bh = h(); - - int X, Y, W, H; - - fl_clip_box( bx, by, bw, bh, X, Y, W, H ); - -// fl_rectf( X, Y, W, H, fl_color_average( FL_BLACK, FL_BACKGROUND_COLOR, 0.3 ) ); -// fl_rectf( X,Y,W,H, fl_color_average( FL_BLACK, FL_WHITE, 0.90 ) ); - fl_rectf( X,Y,W,H, FL_DARK1 ); - - - if ( draw_with_grid ) - { - fl_color( FL_GRAY ); - - const int inc = bh / 10; - if ( inc ) - for ( int gy = 0; gy < bh; gy += inc ) - fl_line( X, by + gy, X + W, by + gy ); - - } - - timeline->draw_measure_lines( X, Y, W, H ); -} - -void -Control_Sequence::draw ( void ) -{ - fl_push_clip( drawable_x(), y(), drawable_w(), h() ); - - const int bx = x(); - const int by = y() + Fl::box_dy( box() ); - const int bw = w(); - const int bh = h() - Fl::box_dh( box() ); - - int X, Y, W, H; - - fl_clip_box( bx, by, bw, bh, X, Y, W, H ); - - bool active = active_r(); - - const Fl_Color color = active ? this->color() : fl_inactive( this->color() ); -// const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() ); - - if ( box() != FL_NO_BOX ) - draw_box(); - - if ( interpolation() != None ) - { - if ( draw_with_polygon ) - { - fl_color( fl_color_add_alpha( color, 60 ) ); - - fl_begin_complex_polygon(); - draw_curve( true ); - fl_end_complex_polygon(); - - } - - fl_color( fl_color_average( FL_WHITE, color, 0.5 ) ); - fl_line_style( FL_SOLID, 2 ); - - fl_begin_line(); - draw_curve( false ); - fl_end_line(); - - fl_line_style( FL_SOLID, 0 ); - } - - if ( interpolation() == None || _highlighted == this || Fl::focus() == this ) - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) - if ( (*r)->x() + (*r)->w() >= bx && - (*r)->x() <= bw + bw ) - (*r)->draw_box(); - else - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) - if ( (*r)->selected() ) - if ( (*r)->x() + (*r)->w() >= bx && - (*r)->x() <= bw + bw ) - (*r)->draw_box(); - - fl_pop_clip(); - - if ( damage() & ~DAMAGE_SEQUENCE ) - { - Fl_Group::draw_children(); - } -} - - -void -Control_Sequence::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Control_Sequence*)v)->menu_cb( (const Fl_Menu_*)w ); -} - -void -Control_Sequence::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[1024]; - - DMESSAGE( "Control_Sequence: menu_cb" ); - - if ( ! m->mvalue() || m->mvalue()->flags & ( FL_SUBMENU_POINTER | FL_SUBMENU )) - return; - - m->item_pathname( picked, sizeof( picked ), m->mvalue() ); - - if ( ! strncmp( picked, "Connect To/", strlen( "Connect To/" ) ) ) - { - char *peer_name = index( picked, '/' ) + 1; - - *index( peer_name, '/' ) = 0; - - const char *path = ((OSC::Signal*)m->mvalue()->user_data())->path(); - - /* if ( ! _osc_output()->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) ) */ - { - _persistent_osc_connections.push_back( strdup(path) ); - - connect_osc(); - } - /* else */ - /* { */ - /* timeline->osc->disconnect_signal( _osc_output(), path ); */ - - /* for ( std::list::iterator i = _persistent_osc_connections.begin(); */ - /* i != _persistent_osc_connections.end(); */ - /* ++i ) */ - /* { */ - /* if ( !strcmp( *i, path ) ) */ - /* { */ - /* free( *i ); */ - /* i = _persistent_osc_connections.erase( i ); */ - /* break; */ - /* } */ - /* } */ - - /* //free( path ); */ - /* } */ - - } - else if ( ! strcmp( picked, "Interpolation/Linear" ) ) - interpolation( Linear ); - else if ( ! strcmp( picked, "Interpolation/None" ) ) - interpolation( None ); - else if ( ! strcmp( picked, "Mode/Control Signal (OSC)" )) - mode( OSC ); - else if ( ! strcmp( picked, "Mode/Control Voltage (JACK)" ) ) - mode( CV ); - - else if ( ! strcmp( picked, "/Rename" ) ) - { - ((Fl_Sometimes_Input*)header()->name_input)->take_focus(); - } - else if ( !strcmp( picked, "/Remove" ) ) - { - Fl::delete_widget( this ); - } - else if ( ! strcmp( picked, "/Color" ) ) - { - unsigned char r, g, b; - - Fl::get_color( color(), r, g, b ); - - if ( fl_color_chooser( "Track Color", r, g, b ) ) - { - color( fl_rgb_color( r, g, b ) ); - } - - redraw(); - } -} - -void -Control_Sequence::connect_osc ( void ) -{ - timeline->osc_thread->lock(); - - if ( _persistent_osc_connections.size() ) - { - for ( std::list::iterator i = _persistent_osc_connections.begin(); - i != _persistent_osc_connections.end(); - ++i ) - { - if ( ! timeline->osc->connect_signal( _osc_output(), *i ) ) - { - /* WARNING( "Failed to connect output %s to %s", _osc_output()->path(), *i ); */ - } - else - { - MESSAGE( "Connected output %s to %s", _osc_output()->path(), *i ); -// tooltip( _osc_connected_path ); - } - } - } - - /* header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); */ - - timeline->osc_thread->unlock(); -} - -void -Control_Sequence::process_osc ( void ) -{ - if ( mode() != OSC ) - return; - - if ( _osc_output() ) - { - sample_t buf[1]; - - *buf = 0; - - play( buf, (nframes_t)transport->frame, (nframes_t) 1 ); - _osc_output()->value( (float)buf[0] ); - } -} - -static Fl_Menu_Button *peer_menu; -static const char *peer_prefix; - -void -Control_Sequence::update_osc_connection_state ( void ) -{ - /* header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); */ -} - -void -Control_Sequence::peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ) -{ - char *s; - - /* only show inputs */ - if ( sig->direction() != OSC::Signal::Input ) - return; - -// DMESSAGE( "Paramter limits: %f %f", sig->parameter_limits().min, sig->parameter_limits().max ); - - /* only list CV signals for now */ - if ( ! ( sig->parameter_limits().min == 0.0 && - sig->parameter_limits().max == 1.0 ) ) - return; - - if ( ! v ) - { - if( state == OSC::Signal::Created ) - timeline->connect_osc(); - else - timeline->update_osc_connection_state(); - } - else - { - /* building menu */ -// const char *name = sig->peer_name(); - - assert( sig->path() ); - - char *path = strdup( sig->path() ); - - unescape_url( path ); - - asprintf( &s, "%s/%s", peer_prefix, path ); - - peer_menu->add( s, 0, NULL, (void*)( sig ), 0 ); - - /* FL_MENU_TOGGLE | */ - /* ( ((Control_Sequence*)v)->_osc_output()->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) ); */ - - free( path ); - - free( s ); - } -} - -void -Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ) -{ - peer_menu = m; - peer_prefix = prefix; - - timeline->osc->list_peer_signals( this ); -} - -Fl_Menu_Button & -Control_Sequence::menu ( void ) -{ - static Fl_Menu_Button _menu( 0, 0, 0, 0, "Control Sequence" ); - - _menu.clear(); - - if ( mode() == OSC ) - { - add_osc_peers_to_menu( &_menu, "Connect To" ); - } - - _menu.add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Mode/Control Voltage (JACK)", 0, 0, 0 ,FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Mode/Control Signal (OSC)", 0, 0, 0 , FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) ); - - _menu.add( "Rename", 0, 0, 0 ); - _menu.add( "Color", 0, 0, 0 ); - _menu.add( "Remove", 0, 0, 0 ); - - _menu.callback( &Control_Sequence::menu_cb, (void*)this); - - return _menu; -} - -int -Control_Sequence::handle ( int m ) -{ - switch ( m ) - { - case FL_ENTER: - break; - case FL_LEAVE: - _highlighted = 0; - damage( DAMAGE_SEQUENCE ); - fl_cursor( FL_CURSOR_DEFAULT ); - break; - case FL_MOVE: - if ( Fl::event_x() > drawable_x() ) - { - if ( _highlighted != this ) - { - _highlighted = this; - damage( DAMAGE_SEQUENCE ); - fl_cursor( FL_CURSOR_CROSS ); - } - } - else - { - if ( _highlighted == this ) - { - _highlighted = 0; - damage( DAMAGE_SEQUENCE ); - fl_cursor( FL_CURSOR_DEFAULT ); - } - } - default: - break; - } - - Logger log(this); - - int r = Sequence::handle( m ); - - if ( r ) - return r; - - switch ( m ) - { - case FL_PUSH: - { - - if ( Fl::event_x() >= drawable_x() && - test_press( FL_BUTTON1 ) ) - { - /* insert new control point */ - timeline->sequence_lock.wrlock(); - - new Control_Point( this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - drawable_x() ), (float)(Fl::event_y() - y()) / h() ); - - timeline->sequence_lock.unlock(); - - return 1; - } - else if ( Fl::event_x() < drawable_x() && - test_press( FL_BUTTON3 ) ) - { - menu_popup( &menu() ); - - return 1; - } - - return Fl_Group::handle( m ); - } - default: - return 0; - } -} diff --git a/timeline/src/Control_Sequence.H b/timeline/src/Control_Sequence.H deleted file mode 100644 index 38e9822..0000000 --- a/timeline/src/Control_Sequence.H +++ /dev/null @@ -1,147 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence.H" -#include "Control_Point.H" - -#include "JACK/Port.H" - -// class JACK::Port; -#include "OSC/Endpoint.H" - -class Control_Sequence_Header; -class Fl_Menu_Button; - -class Control_Sequence : public Sequence -{ - /* not permitted */ - Control_Sequence ( const Control_Sequence &rhs ); - Control_Sequence & operator = ( const Control_Sequence &rhs ); - -public: - - enum Curve_Type { None, Linear, Quadratic }; - - enum Mode { - CV, - OSC, - MIDI - }; - -private: - - static void cb_button ( Fl_Widget *w, void *v ); - void cb_button ( Fl_Widget *w ); - - JACK::Port *_output; - - /* these are used to cache the saved osc connection until the - * session is loaded, at which time we will reconnect */ - std::list _persistent_osc_connections; - /* osc output port */ - volatile void *__osc_output; - - OSC::Signal *_osc_output ( void ) const - { - return (OSC::Signal *)__osc_output; - } - - void _osc_output ( OSC::Signal * s) - { - __osc_output = s; - } - - - static void peer_callback( OSC::Signal *sig, OSC::Signal::State state, void *v ); - void peer_callback( OSC::Signal *sig, OSC::Signal::State state ); - void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix ); - - static Fl_Widget *_highlighted; - - Curve_Type _interpolation; - - void init ( void ); - - void draw_curve ( bool filled ); - - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( const Fl_Menu_ *m ); - - Mode _mode; - - float _rate; - -protected: - - Control_Sequence ( ); - - virtual void get ( Log_Entry &e ) const; - virtual void get_unjournaled ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - void draw_box ( void ); - void draw ( void ); - int handle ( int m ); - - void update_osc_path ( void ); - void update_port_name ( void ); - - - Fl_Menu_Button & menu ( void ); - -public: - - Control_Sequence_Header * header ( void ) { return (Control_Sequence_Header*)child(0); } - - virtual void name ( const char *s ); - virtual const char *name ( void ) const; - - void process_osc ( void ); - void connect_osc ( void ); - void update_osc_connection_state ( void ); - - static bool draw_with_polygon; - static bool draw_with_grid; - - LOG_CREATE_FUNC( Control_Sequence ); - - Control_Sequence ( Track *, const char *name = 0 ); - ~Control_Sequence ( ); - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } - - Curve_Type interpolation ( void ) const { return _interpolation; } - void interpolation ( Curve_Type v ) - { - _interpolation = v; - damage( FL_DAMAGE_USER1 ); - } - - Mode mode ( void ) const { return _mode; } - void mode ( Mode v ); - - /* Engine */ - void output ( JACK::Port *p ) { _output = p; } - nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes ); - nframes_t process ( nframes_t nframes ); - -}; diff --git a/timeline/src/Cursor_Point.C b/timeline/src/Cursor_Point.C deleted file mode 100644 index e953b16..0000000 --- a/timeline/src/Cursor_Point.C +++ /dev/null @@ -1,134 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#include "Cursor_Point.H" -#include "Cursor_Sequence.H" -#include "Timeline.H" // for timeline->time_track - -Cursor_Point::Cursor_Point ( ) -{ -// timeline->->add( this ); - _label = NULL; - _type = NULL; -} - -Cursor_Point::Cursor_Point ( nframes_t when, const char *type, const char *label ) -{ -// _make_label(); - - _label = NULL; - _type = NULL; - - this->label( label ); - this->type( type ); - - timeline->add_cursor( this ); - - start( when ); - - log_create(); -} - -Cursor_Point::Cursor_Point ( const Cursor_Point &rhs ) : Sequence_Point( rhs ) -{ - label( rhs.label() ); - type( rhs.type() ); - - log_create(); -} - -Cursor_Point::~Cursor_Point ( ) -{ -// sequence()->remove( this ); - - log_destroy(); - - label(NULL); - type(NULL); -} - - - -void -Cursor_Point::get ( Log_Entry &e ) const -{ -// Sequence_Point::get( e ); - - e.add( ":start", start() ); - e.add( ":label", label() ); - e.add( ":type", type() ); -} - -void -Cursor_Point::set ( Log_Entry &e ) -{ - - Sequence_Point::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":label" ) ) - label( v ); - else if ( ! strcmp( s, ":type" )) - { - type( v ); - - timeline->add_cursor( this ); - } - -/* /\* FIXME: we need to add this to the time track on creation!!! *\/ */ -/* timeline->time_track->add( this ); */ - - } - - sequence()->handle_widget_change( start(), length() ); - -// _make_label(); -} - - - - -int -Cursor_Point::handle ( int m ) -{ - Logger log( this ); - - /* if ( m == FL_PUSH && Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) ) */ - /* { */ - - /* time_sig t = _time; */ - - /* edit( &t ); */ - - /* time( t.beats_per_bar, t.beat_type ); */ - - /* return 0; */ - - /* } */ - - return Sequence_Point::handle( m ); -} - - diff --git a/timeline/src/Cursor_Point.H b/timeline/src/Cursor_Point.H deleted file mode 100644 index 0cd05b6..0000000 --- a/timeline/src/Cursor_Point.H +++ /dev/null @@ -1,64 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence_Point.H" - - -class Cursor_Point : public Sequence_Point -{ - char *_type; - -protected: - -// const char *class_name ( void ) { return "Time_Point"; } - - virtual void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - Cursor_Point ( ); - -public: - - LOG_CREATE_FUNC( Cursor_Point ); - SEQUENCE_WIDGET_CLONE_FUNC( Cursor_Point ); - -// static bool edit ( time_sig *sig ); - - Cursor_Point ( nframes_t when, const char *type, const char *label ); - Cursor_Point ( const Cursor_Point &rhs ); - - ~Cursor_Point ( ); - - const char * type ( void ) const { return _type; } - void type ( const char *v ) - { - if ( _type ) - free( _type ); - - _type = NULL; - - if ( v ) - _type = strdup( v ); - } - - int handle ( int m ); - -}; diff --git a/timeline/src/Cursor_Region.C b/timeline/src/Cursor_Region.C deleted file mode 100644 index 3c1be5c..0000000 --- a/timeline/src/Cursor_Region.C +++ /dev/null @@ -1,153 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include -#include -#include - -#include "Cursor_Region.H" -#include "Cursor_Sequence.H" -#include "Timeline.H" - -Fl_Color Cursor_Region::box_color ( void ) const -{ - return ((Cursor_Sequence*)sequence())->cursor_color(); -} - - -void Cursor_Region::box_color ( Fl_Color c ) -{ - ((Cursor_Sequence*)sequence())->cursor_color( c ); -} - - - -void -Cursor_Region::get ( Log_Entry &e ) const -{ -// Sequence_Region::get( e ); - e.add( ":start", start() ); - e.add( ":length", length() ); - e.add( ":label", label() ); - e.add( ":type", type() ); -} - -void -Cursor_Region::set ( Log_Entry &e ) -{ - Sequence_Region::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":label" ) ) - label( v ); - if ( ! strcmp( s, ":type" ) ) - { - type( v ); - timeline->add_cursor( this ); - } - } - -// timeline->redraw(); -} - -Cursor_Region::Cursor_Region ( nframes_t when, nframes_t length, const char *type, const char *label ) -{ - _label = NULL; - _type = NULL; - - this->label( label ); - this->type( type ); - - start( when ); - this->length( length ); - - timeline->add_cursor( this ); - - log_create(); -} - -Cursor_Region::Cursor_Region ( const Cursor_Region &rhs ) : Sequence_Region( rhs ) -{ - _label = rhs._label ? strdup( rhs._label ) : NULL; - _type = rhs._type ? strdup( rhs._type ) : NULL; - - log_create(); -} - - -Cursor_Region::~Cursor_Region ( ) -{ -// timeline->cursor_track->remove( this ); - - log_destroy(); - - label(NULL); - type(NULL); -} - -void -Cursor_Region::draw_box ( void ) -{ - Sequence_Region::draw_box(); -} - -void -Cursor_Region::draw ( void ) -{ - draw_label( _label, (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_TOP | FL_ALIGN_CLIP ) ); -} - -#include -#include - -int -Cursor_Region::handle ( int m ) -{ - Logger _log( this ); - - if ( m == FL_PUSH ) - { - if ( test_press( FL_BUTTON3 ) ) - { - char *s = fl_text_edit( "Cursor text:", "&Save", label() ); - - if ( s ) - label( s ); - - free( s ); - - return 0; - } - } - - int r = Sequence_Region::handle( m ); - - if ( m == FL_RELEASE ) - { - sequence()->sort(); - timeline->redraw(); - } - - return r; -} diff --git a/timeline/src/Cursor_Region.H b/timeline/src/Cursor_Region.H deleted file mode 100644 index 3290867..0000000 --- a/timeline/src/Cursor_Region.H +++ /dev/null @@ -1,74 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence_Region.H" -#include "Cursor_Sequence.H" - -class Cursor_Region : public Sequence_Region -{ - /* not permitted */ - Cursor_Region & operator = ( const Cursor_Region &rhs ); - - char *_type; - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - Cursor_Region ( ) - { - _label = NULL; - _type = NULL; - } - - Cursor_Region ( const Cursor_Region &rhs ); - -public: - - virtual Fl_Color box_color ( void ) const; - virtual void box_color ( Fl_Color c ); - - /* for loggable */ - LOG_CREATE_FUNC( Cursor_Region ); - SEQUENCE_WIDGET_CLONE_FUNC( Cursor_Region ); - - Cursor_Region ( nframes_t when, nframes_t length, const char *type, const char *label ); - virtual ~Cursor_Region ( ); - - void draw_box ( void ); - void draw ( void ); - int handle ( int m ); - - - const char * type ( void ) const { return _type; } - void type ( const char *v ) - { - if ( _type ) - free( _type ); - - _type = NULL; - - if ( v ) - _type = strdup( v ); - } - -}; diff --git a/timeline/src/Cursor_Sequence.C b/timeline/src/Cursor_Sequence.C deleted file mode 100644 index 2f683e9..0000000 --- a/timeline/src/Cursor_Sequence.C +++ /dev/null @@ -1,97 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Cursor_Sequence.H" -#include "Cursor_Point.H" -#include "Timeline.H" -#include "Track.H" - -Cursor_Sequence::Cursor_Sequence( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) -{ - _cursor_color = FL_CYAN; - - labeltype(FL_NO_LABEL); - - box( FL_FLAT_BOX ); - - { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); - o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - o->labelsize( 12 ); - o->labeltype( FL_NORMAL_LABEL ); - Fl_Group::add( o ); - } - - resizable(0); -} - - - -void -Cursor_Sequence::label ( const char *s ) -{ - Sequence::label(s); - child(0)->label(s); -} - -const char * -Cursor_Sequence::label ( void ) const -{ - return Sequence::label(); -} - -void -Cursor_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) -{ - sort(); - timeline->redraw_overlay(); - timeline->redraw(); -} - -Sequence_Widget * -Cursor_Sequence::active_cursor ( void ) -{ - if ( _widgets.size() ) - return _widgets.front(); - else - return 0; -} - -int -Cursor_Sequence::handle ( int m ) -{ - int r = Sequence::handle( m ); - - if ( r ) - return r; - - switch ( m ) - { - case FL_PUSH: - /* if ( Fl::event_button1() ) */ - /* { */ - /* add( new Cursor_Point( timeline->x_to_offset( Fl::event_x() ), "NONE" ) ); */ - /* timeline->redraw(); */ - /* return 0; */ - /* } */ - return 0; - default: - return 0; - - } -} diff --git a/timeline/src/Cursor_Sequence.H b/timeline/src/Cursor_Sequence.H deleted file mode 100644 index 57fe5f7..0000000 --- a/timeline/src/Cursor_Sequence.H +++ /dev/null @@ -1,53 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence.H" -#include "Cursor_Point.H" -#include "Cursor_Region.H" - -class Cursor_Sequence : public Sequence -{ - - Fl_Color _cursor_color; - -protected: - - /* not used */ - void get ( Log_Entry & ) const { } - void set ( Log_Entry & ) { } - -public: - - void label ( const char * s ); - const char *label ( void ) const; - - Sequence_Widget *active_cursor ( void ); - - Fl_Color cursor_color ( void ) const { return _cursor_color; } - void cursor_color ( Fl_Color c ) { _cursor_color = c; } - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - - Cursor_Sequence ( int X, int Y, int W, int H ); - - void handle_widget_change ( nframes_t start, nframes_t length ); - int handle ( int m ); -}; diff --git a/timeline/src/Engine/Audio_File.C b/timeline/src/Engine/Audio_File.C deleted file mode 100644 index 0d70346..0000000 --- a/timeline/src/Engine/Audio_File.C +++ /dev/null @@ -1,196 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Audio_File.H" -#include "Audio_File_SF.H" -#include "Audio_File_Dummy.H" - -#include "const.h" -#include "debug.h" -#include "Block_Timer.H" - -#include - -std::map Audio_File::_open_files; - -Audio_File::~Audio_File ( ) -{ - DMESSAGE( "Freeing Audio_File object for \"%s\"", _filename ); - - _open_files[ std::string( _filename ) ] = NULL; - - if ( _filename ) - free( _filename ); - - if ( _path ) - free( _path ); -} - -const Audio_File::format_desc * -Audio_File::find_format ( const format_desc *fd, const char *name ) -{ - for ( ; fd->name; ++fd ) - if ( ! strcmp( fd->name, name ) ) - return fd; - - return NULL; -} - -void -Audio_File::all_supported_formats ( std::list &formats ) -{ - const format_desc *fd; - - fd = Audio_File_SF::supported_formats; - - for ( ; fd->name; ++fd ) - formats.push_back( fd->name ); -} - -static bool -is_absolute ( const char *name ) -{ - return *name == '/'; -} - -/** return pointer to /name/ corrected for relative path. */ -char *Audio_File::path ( const char *name ) -{ - char *path = 0; - - if ( is_absolute( name ) ) - path = strdup( name ); - else - asprintf( &path, "sources/%s", name ); - - return path; -} - -const char * -Audio_File::filename ( void ) const -{ - return _path; -} - -static bool is_poor_seeker ( const char * filename ) -{ - if ( ( strlen(filename) > 4 && - ! strcasecmp( &filename[strlen(filename)-4], ".ogg" ) ) - || - ( strlen(filename) > 5 && - ! strcasecmp( &filename[strlen(filename)-5], ".flac" ) ) - ) - { - return true; - } - - return false; -} - -/** attempt to open any supported filetype */ -Audio_File * -Audio_File::from_file ( const char * filename ) -{ - Block_Timer timer( "Opened audio file" ); - - Audio_File *a; - - if ( is_poor_seeker(filename) ) - { - /* OGG and FLAC have poor seek performance, so they require - * separate file descriptors to be useful */ - } - else - { - /* WAV are quick enough to seek that we can save - * filedescriptors by sharing them between regions */ - if ( ( a = _open_files[ std::string( filename ) ] ) ) - { - ++a->_refs; - - return a; - } - } - - if ( ( a = Audio_File_SF::from_file( filename ) ) ) - goto done; - -// TODO: other formats - - DWARNING( "creating dummy source for \"%s\"", filename ); - - /* FIXME: wrong place for this? */ - if ( ( a = Audio_File_Dummy::from_file( filename ) ) ) - goto done; - - return NULL; - -done: - - /* ASSERT( ! _open_files[ std::string( filename ) ], "Programming errror" ); */ - - _open_files[ std::string( filename ) ] = a; - - return a; -} - -Audio_File * -Audio_File::duplicate ( void ) -{ - if ( is_poor_seeker( _filename ) ) - { - return from_file(_filename); - } - else - { - ++_refs; - return this; - } -} - -/** release the resources assoicated with this audio file if no other - * references to it exist */ -void -Audio_File::release ( void ) -{ - if ( --_refs == 0 ) - delete this; -} - - -bool -Audio_File::read_peaks( float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ) -{ - *peaks = 0; - *channels = 0; - *pbuf = NULL; - - if ( dummy() ) - return false; - else - { - *peaks = _peaks.fill_buffer( fpp, start, end ); - - *channels = this->channels(); - - *pbuf = _peaks.peakbuf(); - - return true; - } -} diff --git a/timeline/src/Engine/Audio_File.H b/timeline/src/Engine/Audio_File.H deleted file mode 100644 index baeedee..0000000 --- a/timeline/src/Engine/Audio_File.H +++ /dev/null @@ -1,108 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -/* Base class for all audio file library interfaces */ - -#include -#include -#include -#include - -#include "types.h" -#include "Mutex.H" -#include "Peaks.H" - -class Peak_Writer; - -class Audio_File : protected Mutex -{ - int _refs; - - static std::map _open_files; - - /* not permitted */ - Audio_File ( const Audio_File &rhs ); - const Audio_File & operator= ( const Audio_File &rhs ); - -protected: - - struct format_desc - { - const char *name; - const char *extension; - unsigned long id; - int quality; - }; - - char *_filename; - char *_path; - - volatile nframes_t _length; /* length of file in samples */ - nframes_t _samplerate; /* sample rate */ - int _channels; - - Peaks _peaks; - - static const format_desc * find_format ( const format_desc *fd, const char *name ); - - static char *path ( const char *name ); - -public: - - Audio_File ( ) : _peaks( this ) - { - _path =_filename = NULL; - _samplerate = 0; - _length = _channels = 0; - _refs = 1; - } - - virtual ~Audio_File ( ); - - virtual bool dummy ( void ) const { return false; } - - static void all_supported_formats ( std::list &formats ); - - static Audio_File *from_file ( const char *filename ); - - void release ( void ); - Audio_File *duplicate ( void ); - - Peaks const * peaks ( ) { return &_peaks; } - const char *filename ( void ) const; - const char *name ( void ) const { return _filename; } - nframes_t length ( void ) const { return _length; } - int channels ( void ) const { return _channels; } - nframes_t samplerate ( void ) const { return _samplerate; } -// Peaks const * peaks ( void ) { return &_peaks; } - - virtual bool open ( void ) = 0; - virtual void close ( void ) = 0; - virtual void seek ( nframes_t offset ) = 0; - virtual nframes_t read ( sample_t *buf, int channel, nframes_t len ) = 0; - virtual nframes_t read ( sample_t *buf, int channel, nframes_t start, nframes_t len ) = 0; - virtual nframes_t write ( sample_t *buf, nframes_t len ) = 0; - - virtual void finalize ( void ) { _peaks.finish_writing(); } - - bool read_peaks( float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ); - -}; diff --git a/timeline/src/Engine/Audio_File_Dummy.C b/timeline/src/Engine/Audio_File_Dummy.C deleted file mode 100644 index b91ede9..0000000 --- a/timeline/src/Engine/Audio_File_Dummy.C +++ /dev/null @@ -1,30 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Audio_File_Dummy.H" - -#include - -Audio_File_Dummy * -Audio_File_Dummy::from_file ( const char *filename ) -{ - Audio_File_Dummy *d = new Audio_File_Dummy; - d->_filename = strdup( filename ); - return d; -} diff --git a/timeline/src/Engine/Audio_File_Dummy.H b/timeline/src/Engine/Audio_File_Dummy.H deleted file mode 100644 index 331e3f9..0000000 --- a/timeline/src/Engine/Audio_File_Dummy.H +++ /dev/null @@ -1,46 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Audio_File.H" - -class Audio_File_Dummy : public Audio_File -{ - Audio_File_Dummy ( ) - { - } - -public: - - static Audio_File_Dummy *from_file ( const char *filename ); - - bool dummy ( void ) const { return true; } - - ~Audio_File_Dummy ( ) - { - } - - bool open ( void ) { return true; } - void close ( void ) { } - void seek ( nframes_t ) { } - nframes_t read ( sample_t *, int, nframes_t len ) { return 0; } - nframes_t read ( sample_t *, int, nframes_t start, nframes_t end ) { return 0; } - nframes_t write ( sample_t *, nframes_t nframes ) { return nframes; } -}; diff --git a/timeline/src/Engine/Audio_File_SF.C b/timeline/src/Engine/Audio_File_SF.C deleted file mode 100644 index a1ef61f..0000000 --- a/timeline/src/Engine/Audio_File_SF.C +++ /dev/null @@ -1,267 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Audio_File_SF.H" -// #include "Timeline.H" - -#include - -#include -#include - -#include - -#include "Peaks.H" - -// #define HAS_SF_FORMAT_VORBIS - -#include "const.h" -#include "debug.h" -#include - - - -const Audio_File::format_desc Audio_File_SF::supported_formats[] = -{ - { "Wav 24", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, - { "Wav 16", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, - { "Wav f32", "wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT | SF_ENDIAN_FILE }, - { "W64 24", "w64", SF_FORMAT_W64 | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, - { "W64 16", "w64", SF_FORMAT_W64 | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, - { "W64 f32", "w64", SF_FORMAT_W64 | SF_FORMAT_FLOAT | SF_ENDIAN_FILE }, - { "Au 24", "au", SF_FORMAT_AU | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, - { "Au 16", "au", SF_FORMAT_AU | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, - { "FLAC", "flac", SF_FORMAT_FLAC | SF_FORMAT_PCM_24 }, -#ifdef HAVE_SF_FORMAT_VORBIS - { "Vorbis q10", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 10 }, - { "Vorbis q6", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 6 }, - { "Vorbis q3", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 3 }, -#endif - { 0, 0 } -}; - - - -Audio_File_SF * -Audio_File_SF::from_file ( const char *filename ) -{ - SNDFILE *in; - SF_INFO si; - - Audio_File_SF *c = NULL; - - memset( &si, 0, sizeof( si ) ); - - char *fp = path( filename ); - - if ( ! ( in = sf_open( fp, SFM_READ, &si ) ) ) - return NULL; - -/* if ( si.samplerate != timeline->sample_rate() ) */ -/* { */ -/* printf( "error: samplerate mismatch!\n" ); */ -/* goto invalid; */ -/* } */ - - c = new Audio_File_SF; - -// c->_peak_writer = NULL; - c->_current_read = 0; - c->_filename = strdup( filename ); - c->_path = fp; - c->_length = si.frames; - c->_samplerate = si.samplerate; - c->_channels = si.channels; - - c->_in = in; -// sf_close( in ); - - return c; - -//invalid: - - sf_close( in ); - return NULL; -} - -Audio_File_SF * -Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels, const char *format ) -{ - SF_INFO si; - SNDFILE *out; - - memset( &si, 0, sizeof( si ) ); - - - const Audio_File::format_desc *fd = Audio_File::find_format( Audio_File_SF::supported_formats, format ); - - if ( ! fd ) - return (Audio_File_SF *)1; - - si.samplerate = samplerate; - si.channels = channels; - si.format = fd->id; - - char *name; - asprintf( &name, "%s.%s", filename, fd->extension ); - - char *filepath = path( name ); - - if ( ! ( out = sf_open( filepath, SFM_WRITE, &si ) ) ) - { - printf( "couldn't create soundfile.\n" ); - free( name ); - return NULL; - } - - if ( !strcmp( fd->extension, "ogg" ) ) - { - /* set high quality encoding for vorbis */ - double quality = ( fd->quality + 1 ) / (float)11; - - sf_command( out, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof( double ) ); - } - - Audio_File_SF *c = new Audio_File_SF; - - c->_path = filepath; - c->_filename = name; - c->_length = 0; - c->_samplerate = samplerate; - c->_channels = channels; - - c->_in = out; - - c->_peaks.prepare_for_writing(); - - return c; -} - -bool -Audio_File_SF::open ( void ) -{ - SF_INFO si; - - assert( _in == NULL ); - - memset( &si, 0, sizeof( si ) ); - - if ( ! ( _in = sf_open( _path, SFM_READ, &si ) ) ) - return false; - - _current_read = 0; - _length = si.frames; - _samplerate = si.samplerate; - _channels = si.channels; - -// seek( 0 ); - return true; -} - -void -Audio_File_SF::close ( void ) -{ - if ( _in ) - sf_close( _in ); - - _in = NULL; -} - -void -Audio_File_SF::seek ( nframes_t offset ) -{ - lock(); - - if ( offset != _current_read ) - sf_seek( _in, _current_read = offset, SEEK_SET | SFM_READ ); - - unlock(); -} - -/* if channels is -1, then all channels are read into buffer - (interleaved). buf should be big enough to hold them all */ -nframes_t -Audio_File_SF::read ( sample_t *buf, int channel, nframes_t len ) -{ - if ( len > 256 * 100 ) - WARNING( "warning: attempt to read an insane number of frames (%lu) from soundfile\n", (unsigned long)len ); - -// printf( "len = %lu, channels = %d\n", len, _channels ); - - lock(); - - nframes_t rlen; - - if ( _channels == 1 || channel == -1 ) - rlen = sf_readf_float( _in, buf, len ); - else - { - sample_t *tmp = new sample_t[ len * _channels ]; - - rlen = sf_readf_float( _in, tmp, len ); - - /* extract the requested channel */ - for ( unsigned int i = channel; i < rlen * _channels; i += _channels ) - *(buf++) = tmp[ i ]; - - delete[] tmp; - } - - _current_read += rlen; - - unlock(); - - return rlen; -} - -/** read samples from /start/ to /end/ into /buf/ */ -nframes_t -Audio_File_SF::read ( sample_t *buf, int channel, nframes_t start, nframes_t len ) -{ - lock(); -// open(); - - seek( start ); - - nframes_t cnt = read( buf, channel, len ); - - unlock(); - -// close(); - - return cnt; -} - -/** write /nframes/ from /buf/ to soundfile. Should be interleaved for - * the appropriate number of channels */ -nframes_t -Audio_File_SF::write ( sample_t *buf, nframes_t nframes ) -{ - _peaks.write( buf, nframes ); - - lock(); - - nframes_t l = sf_writef_float( _in, buf, nframes ); - - _length += l; - - unlock(); - - return l; -} diff --git a/timeline/src/Engine/Audio_File_SF.H b/timeline/src/Engine/Audio_File_SF.H deleted file mode 100644 index 8ab9a75..0000000 --- a/timeline/src/Engine/Audio_File_SF.H +++ /dev/null @@ -1,63 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Audio_File.H" - -#include - -class Audio_File_SF : public Audio_File -{ -// Audio_File_SF ( const char *filename ) - - SNDFILE *_in; - - /* used to avoid unnecessary seeking--libsndfile isn't smart - * enough to do this for us */ - volatile nframes_t _current_read; - - Audio_File_SF ( ) - { - _in = 0; - _current_read = 0; - } - -public: - - static const Audio_File::format_desc supported_formats[]; - - static Audio_File_SF *from_file ( const char *filename ); - static Audio_File_SF *create ( const char *filename, nframes_t samplerate, int channels, const char *format ); - - - ~Audio_File_SF ( ) - { - /* stupid C++ */ - close(); - } - - bool open ( void ); - void close ( void ); - void seek ( nframes_t offset ); - nframes_t read ( sample_t *buf, int channel, nframes_t len ); - nframes_t read ( sample_t *buf, int channel, nframes_t start, nframes_t len ); - nframes_t write ( sample_t *buf, nframes_t nframes ); - -}; diff --git a/timeline/src/Engine/Audio_Region.C b/timeline/src/Engine/Audio_Region.C deleted file mode 100644 index e96e215..0000000 --- a/timeline/src/Engine/Audio_Region.C +++ /dev/null @@ -1,371 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/**********/ -/* Engine */ -/**********/ - -#include "../Audio_Region.H" - -#include "Audio_File.H" -#include "dsp.h" - -#include "const.h" -#include "const.h" -#include "debug.h" -#include "Thread.H" - - - -/** Apply a (portion of) fade from /start/ to a buffer up to size /nframes/. */ -void -Audio_Region::Fade::apply ( sample_t *buf, Audio_Region::Fade::fade_dir_e dir, nframes_t start, nframes_t nframes ) const -{ -// printf( "apply fade %s: start=%ld end=%lu\n", dir == Fade::Out ? "out" : "in", start, end ); - if ( ! nframes ) - return; - - nframes_t n = nframes; - - const double inc = increment(); - double fi = start / (double)length; - - if ( dir == Fade::Out ) - { - fi = 1.0f - fi; - for ( ; n--; fi -= inc ) - *(buf++) *= gain( fi ); - } - else - for ( ; n--; fi += inc ) - *(buf++) *= gain( fi ); -} - -void -Audio_Region::Fade::apply_interleaved ( sample_t *buf, Audio_Region::Fade::fade_dir_e dir, nframes_t start, nframes_t nframes, int channels ) const -{ -// printf( "apply fade %s: start=%ld end=%lu\n", dir == Fade::Out ? "out" : "in", start, end ); - if ( ! nframes ) - return; - - nframes_t n = nframes; - - const double inc = increment(); - double fi = start / (double)length; - - if ( n > length - start ) - /* don't try to apply fade to more samples than specified by the fade length... */ - n = length - start; - - /* ASSERT( nframes < length - start, "Attempt to apply fade to more samples than its length" ); */ - - if ( dir == Fade::Out ) - { - fi = 1.0 - fi; - for ( ; n--; fi -= inc ) - { - const float g = gain(fi); - - for ( int i = channels; i--; ) - *(buf++) *= g; - } - } - else - for ( ; n--; fi += inc ) - { - const float g = gain(fi); - - for ( int i = channels; i--; ) - *(buf++) *= g; - } -} - -static -void -apply_fade ( sample_t *buf, const int channels, Audio_Region::Fade fade, const nframes_t bS, const nframes_t bE, const nframes_t edge, Audio_Region::Fade::fade_dir_e dir ) -{ - const nframes_t bSS = dir == Audio_Region::Fade::Out ? bS + fade.length : bS; - const nframes_t fade_start = bSS > edge ? bSS - edge : 0; - const nframes_t fade_offset = bSS > edge ? 0 : edge - bSS; - - fade.apply_interleaved( buf + ( channels * fade_offset ), dir, fade_start, (bE - bS) - fade_offset, channels ); -}; - -/** read the overlapping at /pos/ for /nframes/ of this region into - /buf/, where /pos/ is in timeline frames. /buf/ is an interleaved - buffer of /channels/ channels */ -/* this runs in the diskstream thread. */ -nframes_t -Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t nframes, int channels ) const -{ - THREAD_ASSERT( Playback ); - - const Range r = _range; - - const nframes_t rS = r.start; - const nframes_t rE = r.start + r.length; - const nframes_t bS = pos; - const nframes_t bE = pos + nframes; - - /* do nothing if region isn't inside buffer */ - if ( bS > rE || bE < rS ) - return 0; - - sample_t *cbuf = NULL; - - if ( buf_is_empty && channels == _clip->channels() ) - { - /* in this case we don't need a temp buffer */ - cbuf = buf; - } - else - { - /* temporary buffer to hold interleaved samples from the clip */ - cbuf = buffer_alloc( _clip->channels() * nframes ); - memset(cbuf, 0, _clip->channels() * sizeof(sample_t) * nframes ); - } - - /* calculate offsets into file and sample buffer */ - - const nframes_t sO = bS < rS ? 0 : bS - rS; /* offset into source */ - const nframes_t bO = bS < rS ? rS - bS : 0; /* offset into buffer (when region start is after beginning of buffer) */ - - nframes_t cnt = nframes; /* number of frames to read */ - - /* if region ends within this buffer, don't read beyond end */ - if ( bE > rE ) - cnt = nframes - ( bE - rE ); - - cnt -= bO; - - const nframes_t len = cnt; - - /* FIXME: keep the declick defults someplace else */ - Fade declick; - - declick.length = (float)timeline->sample_rate() * 0.01f; - declick.type = Fade::Sigmoid; - - /* FIXME: what was this for? */ - if ( bO >= nframes ) - { - cnt = 0; - goto done; - } - - /* FIXME: what was this for? */ - if ( len == 0 ) - { - cnt = 0; - goto done; - } - - /* now that we know how much and where to read, get on with it */ - - // printf( "reading region ofs = %lu, sofs = %lu, %lu-%lu\n", ofs, sofs, start, end ); - - if ( _loop ) - { - if ( _loop < nframes ) - { - /* very small loop or very large buffer... */ - WARNING("Loop size (%lu) is smaller than buffer size (%lu). Behavior undefined.", _loop, nframes ); - } - - const nframes_t lO = sO % _loop; /* how far we are into the loop */ - const nframes_t nthloop = sO / _loop; /* which loop iteration */ - const nframes_t seam_L = rS + ( nthloop * _loop ); /* receding seam */ - const nframes_t seam_R = rS + ( (nthloop + 1 ) * _loop ); /* upcoming seam */ - - /* read interleaved channels */ - if ( seam_R > bS && seam_R < bE ) - { - /* this buffer covers a loop boundary */ - - /* read the first part */ - cnt = _clip->read( cbuf + ( _clip->channels() * bO ), -1, r.offset + lO, ( seam_R - bS ) - bO ); - /* read the second part */ - cnt += _clip->read( cbuf + ( _clip->channels() * ( bO + cnt ) ), -1, r.offset + 0, ( len - cnt ) - bO ); - - /* assert( cnt == len ); */ - } - else - /* buffer contains no loop seam, perform straight read. */ - cnt = _clip->read( cbuf + ( _clip->channels() * bO ), -1, r.offset + lO, cnt ); - - for ( int i = 0; i < 2; i++ ) - { - nframes_t seam = i ? seam_R : seam_L; - - if ( seam != rS && seam != rE ) /* not either end of the region */ - { - if ( seam >= bS && seam <= bE + declick.length ) - /* fade out previous loop segment */ - apply_fade( cbuf, _clip->channels(), declick, bS, bE, seam, Fade::Out ); - - if ( seam <= bE && seam + declick.length >= bS ) - /* fade in next loop segment */ - apply_fade( cbuf, _clip->channels(), declick, bS, bE, seam, Fade::In ); - } - } - } - else - { -// DMESSAGE("Clip read, rL=%lu, b0=%lu, sO=%lu, r.offset=%lu, len=%lu",r.length,bO,sO,r.offset,len); - cnt = _clip->read( cbuf + ( _clip->channels() * bO ), -1, sO + r.offset, len ); - } - - if ( ! cnt ) - goto done; - - /* apply gain */ - - /* just do the whole buffer so we can use the alignment optimized - * version when we're in the middle of a region, this will be full - * anyway */ - buffer_apply_gain( cbuf, nframes * _clip->channels(), _scale ); - - /* perform fade/declicking if necessary */ - { - assert( cnt <= nframes ); - - Fade fade; - - fade = declick < _fade_in ? _fade_in : declick; - - /* do fade in if necessary */ - if ( sO < fade.length ) - apply_fade( cbuf, _clip->channels(), fade, bS, bE, rS, Fade::In ); - - fade = declick < _fade_out ? _fade_out : declick; - - /* do fade out if necessary */ - if ( sO + cnt + fade.length > r.length ) - apply_fade( cbuf, _clip->channels(), fade, bS, bE, rE, Fade::Out ); - } - - if ( buf != cbuf ) - { - /* now interleave the clip channels into the playback buffer */ - for ( int i = 0; i < channels && i < _clip->channels(); i++ ) - { - if ( buf_is_empty ) - buffer_interleaved_copy( buf, cbuf, i, i, channels, _clip->channels(), nframes ); - else - buffer_interleaved_mix( buf, cbuf, i, i, channels, _clip->channels(), nframes ); - - } - } - -done: - - if ( buf != cbuf ) - { - free( cbuf ); - } - - return cnt; -} - -/** prepare for capturing */ -void -Audio_Region::prepare ( void ) -{ - THREAD_ASSERT( Capture ); - - DMESSAGE( "Preparing capture region" ); - -// log_start(); -} - - -class SequenceRedrawRequest { -public: - nframes_t start; - nframes_t length; - Sequence *sequence; -}; - -static -void -sequence_redraw_request_handle ( void *v ) -{ - THREAD_ASSERT(UI); - - SequenceRedrawRequest *o = (SequenceRedrawRequest*)v; - - o->sequence->damage( FL_DAMAGE_USER1, timeline->offset_to_x( o->start ), o->sequence->y(), timeline->ts_to_x( o->length ), o->sequence->h() ); - - delete o; -}; - -/** write /nframes/ from /buf/ to source. /buf/ is interleaved and - must match the channel layout of the write source! */ -nframes_t -Audio_Region::write ( nframes_t nframes ) -{ - THREAD_ASSERT( Capture ); - - if ( 0 == ( timeline->ts_to_x( _range.length ) % 20 ) ) - { - int W = 20; - - if ( W ) - { - SequenceRedrawRequest *o = new SequenceRedrawRequest(); - o->sequence = sequence(); - o->start = _range.start + ( _range.length - timeline->x_to_ts( 20 ) ); - o->length = timeline->x_to_ts( 20 ); - - Fl::awake(sequence_redraw_request_handle, o); - } - } - - timeline->sequence_lock.wrlock(); - - _range.length += nframes; - - timeline->sequence_lock.unlock(); - - return nframes; -} - -/** finalize region capture. Assumes that this *is* a captured region - and that no other regions refer to the same source */ -bool -Audio_Region::finalize ( nframes_t frame ) -{ - THREAD_ASSERT( Capture ); - - DMESSAGE( "finalizing capture region" ); - - timeline->sequence_lock.wrlock(); - - _range.length = frame - _range.start; - - timeline->sequence_lock.unlock(); - - _clip->close(); - _clip->open(); - - log_create(); -// log_end(); - - return true; -} diff --git a/timeline/src/Engine/Audio_Sequence.C b/timeline/src/Engine/Audio_Sequence.C deleted file mode 100644 index cda9eda..0000000 --- a/timeline/src/Engine/Audio_Sequence.C +++ /dev/null @@ -1,63 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../Audio_Sequence.H" - -#include "dsp.h" - -#include "const.h" -#include "debug.h" -#include "Thread.H" - -using namespace std; - - - -/**********/ -/* Engine */ -/**********/ - -/** determine region coverage and fill /buf/ with interleaved samples - * from /frame/ to /nframes/ for exactly /channels/ channels. */ -nframes_t -Audio_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ) -{ - THREAD_ASSERT( Playback ); - - bool buf_is_empty = true; - - /* quick and dirty--let the regions figure out coverage for themselves */ - for ( list ::const_iterator i = _widgets.begin(); - i != _widgets.end(); ++i ) - { - const Audio_Region *r = (Audio_Region*)(*i); - - int nfr; - - /* read mixes into buf */ - if ( ! ( nfr = r->read( buf, buf_is_empty, frame, nframes, channels ) ) ) - /* error ? */ - continue; - - buf_is_empty = false; - } - - /* FIXME: bogus */ - return nframes; -} diff --git a/timeline/src/Engine/Control_Sequence.C b/timeline/src/Engine/Control_Sequence.C deleted file mode 100644 index f334e65..0000000 --- a/timeline/src/Engine/Control_Sequence.C +++ /dev/null @@ -1,135 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../Control_Sequence.H" - -#include "../Transport.H" // for ->frame - -#include "const.h" -#include "debug.h" -#include "Thread.H" - -#include -using std::list; - - - -/**********/ -/* Engine */ -/**********/ - -static inline float -linear_interpolate ( float y1, float y2, float mu ) -{ -// return y1 + mu * ( y2 - y1 ); - return y1 * ( 1.0f - mu ) + y2 * mu; -} - -static inline float -sigmoid_interpolate ( float y1, float y2, float mu ) -{ - return linear_interpolate( y1, y2, ( 1 - cos( mu * M_PI ) ) / 2 ); -} - - - -/** fill buf with /nframes/ of interpolated control curve values - * starting at /frame/ */ -nframes_t -Control_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes ) -{ - // THREAD_ASSERT( RT ); - - Control_Point *p2, *p1 = (Control_Point*)_widgets.front(); - - nframes_t n = nframes; - - for ( list ::const_iterator i = _widgets.begin(); - i != _widgets.end(); ++i, p1 = p2 ) - { - p2 = (Control_Point*)(*i); - - if ( ! n ) - /* buffer's full, no point in continuing */ - break; - - if ( p2->when() < frame ) - { - if ( p2 != _widgets.back() ) - continue; - - /* no more control points left, fill buffer with last value */ - const float v = 1.0f - p2->control(); - - while ( n && n-- ) - *(buf++) = v; - - break; - } - else - { - /* do incremental linear interpolation */ - - const nframes_t len = p1 != p2 ? - p2->when() - p1->when() : - p1->when(); - - const float y1 = 1.0f - p1->control(); - const float y2 = 1.0f - p2->control(); - - const nframes_t start = frame > p1->when() ? - frame - p1->when() : - frame; - - float incr; - - if ( interpolation() != None ) - incr = ( y2 - y1 ) / (float)len; - else - incr = 0.0f; - - float v = y1 + start * incr; - - for ( nframes_t i = start; - i < start + len && n && n--; - ++i, v += incr ) - *(buf++) = v; - } - } - - return nframes - n; -} - -nframes_t -Control_Sequence::process ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - if ( ! _output ) - return nframes; - - if ( _output->connected() ) /* don't waste CPU on disconnected ports */ - { - void *buf = _output->buffer( nframes ); - - return play( (sample_t*)buf, transport->frame, nframes ); - } - else - return nframes; -} diff --git a/timeline/src/Engine/Disk_Stream.C b/timeline/src/Engine/Disk_Stream.C deleted file mode 100644 index 7268e67..0000000 --- a/timeline/src/Engine/Disk_Stream.C +++ /dev/null @@ -1,236 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../Track.H" -// #include "Audio_Sequence.H" -class Audio_Sequence; - -// #include "Port.H" -#include "Engine.H" // for locking. - -#include "Disk_Stream.H" -#include "dsp.h" - -#include "const.h" -#include "debug.h" - -#include - - - -/**********/ -/* Engine */ -/**********/ - -/* A Disk_Stream uses a separate I/O thread to stream a track's - regions from disk into a ringbuffer to be processed by the RT - thread (or vice-versa). The I/O thread syncronizes access with the - user thread via the Timeline mutex. The size of the buffer (in - seconds) must be set before any Disk_Stream objects are created; - that is, at startup time. The default is 5 seconds, which may or - may not be excessive depending on various external factors. */ - -float Disk_Stream::seconds_to_buffer = 2.0f; -/* this is really only a rough estimate. The actual amount of data - read depends on many factors. Overlapping regions, for example, will - require more data to be read from disk, as will varying channel - counts.*/ -size_t Disk_Stream::disk_io_kbytes = 256; - - - -Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track ) -{ - assert( channels ); - - _frame = 0; - _terminate = false; - _pending_seek = false; - _seek_frame = 0; - _xruns = 0; - _frame_rate = frame_rate; - - sem_init( &_blocks, 0, 0 ); - - _resize_buffers( nframes, channels ); -} - -Disk_Stream::~Disk_Stream ( ) -{ - /* it isn't safe to do all this with the RT thread running */ - -// timeline->wrlock(); - - _track = NULL; - - sem_destroy( &_blocks ); - - for ( int i = channels(); i--; ) - { - jack_ringbuffer_free( _rb[ i ] ); - _rb[i] = 0; - } - -// timeline->unlock(); -} - - - -/** flush buffers and reset. Must only be called from the RT thread. */ -void -Disk_Stream::base_flush ( bool is_output ) -{ -// THREAD_ASSERT( RT ); - - /* flush buffers */ - for ( unsigned int i = _rb.size(); i--; ) - jack_ringbuffer_reset( _rb[ i ] ); - - sem_destroy( &_blocks ); - - if ( is_output ) - sem_init( &_blocks, 0, _total_blocks ); - else - sem_init( &_blocks, 0, 0 ); -} - -/** signal thread to terminate, then detach it */ -void -Disk_Stream::detach ( void ) -{ - _terminate = true; - - block_processed(); - - _thread.detach(); -} - -/** stop the IO thread. */ -void -Disk_Stream::shutdown ( void ) -{ - if ( _thread.running() ) - { - DMESSAGE( "Sending terminate signal to diskthread." ); - - _terminate = true; - - /* try to wake the thread so it'll see that it's time to die */ - while ( _terminate ) - { - block_processed(); - usleep( 10 * 1000 ); - } - } - - /* thread may have terminated on it's own (due to punch out..), in - * any case join to clean up */ - _thread.join(); - - DMESSAGE( "diskthread joined." ); - -} - -Track * -Disk_Stream::track ( void ) const -{ - return _track; -} - -Audio_Sequence * -Disk_Stream::sequence ( void ) const -{ - return (Audio_Sequence*)_track->sequence(); -} - -/** start Disk_Stream thread */ -void -Disk_Stream::run ( void ) -{ - ASSERT( ! _thread.running(), "Thread is already running" ); - - if ( ! _thread.clone( &Disk_Stream::disk_thread, this ) ) - FATAL( "Could not create IO thread!" ); -} - -void -Disk_Stream::_resize_buffers ( nframes_t nframes, int channels ) -{ - for ( int i = _rb.size(); i--; ) - jack_ringbuffer_free( _rb[ i ] ); - - _rb.clear(); - - _nframes = nframes; - - _total_blocks = ( _frame_rate * seconds_to_buffer ) / nframes; - - size_t bufsize = _total_blocks * nframes * sizeof( sample_t ); - - if ( disk_io_kbytes ) - _disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 ); - else - _disk_io_blocks = 1; - - for ( int i = channels; i--; ) - _rb.push_back( jack_ringbuffer_create( bufsize ) ); -} - -/* THREAD: RT (non-RT) */ -/* to be called when the JACK buffer size changes. */ -void -Disk_Stream::resize_buffers ( nframes_t nframes ) -{ - if ( nframes != _nframes ) - { - DMESSAGE( "resizing buffers" ); - - const bool was_running = _thread.running(); - - if ( was_running ) - shutdown(); - - _resize_buffers( nframes, channels() ); - - flush(); - - if ( was_running ) - run(); - } -} - - -/* static wrapper */ -void * -Disk_Stream::disk_thread ( void *arg ) -{ - ((Disk_Stream*)arg)->disk_thread(); - - return NULL; -} - -int -Disk_Stream::buffer_percent ( void ) -{ - int n; - - sem_getvalue( &_blocks, &n ); - - return 100 - (n * 100 / _total_blocks); -} diff --git a/timeline/src/Engine/Disk_Stream.H b/timeline/src/Engine/Disk_Stream.H deleted file mode 100644 index 7c3541b..0000000 --- a/timeline/src/Engine/Disk_Stream.H +++ /dev/null @@ -1,126 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - - -#include -#include -#include - -#include - -#include "types.h" -#include "Mutex.H" -#include "const.h" -#include "debug.h" -#include "Thread.H" - -class Track; -class Audio_Sequence; - -class Disk_Stream : public Mutex -{ - - /* not permitted */ - Disk_Stream ( const Disk_Stream &rhs ); - Disk_Stream & operator = ( const Disk_Stream &rhs ); - - -protected: - - Thread _thread; /* io thread */ - - Track *_track; /* Track we belong to */ - - nframes_t _nframes; /* buffer size */ - - - std::vector < jack_ringbuffer_t * >_rb; /* one ringbuffer for each channel */ - - sem_t _blocks; /* semaphore to wake the IO thread with */ - - nframes_t _total_blocks; /* total number of blocks that we can buffer */ - nframes_t _disk_io_blocks; /* the number of blocks to read/write to/from disk at once */ - - - nframes_t _frame_rate; /* used for buffer size calculations */ - - volatile nframes_t _frame; /* location of disk read */ - volatile nframes_t _seek_frame; /* absolute transport position to seek to */ - volatile bool _pending_seek; /* absolute transport position to seek to */ - volatile int _terminate; - - volatile int _xruns; - - int channels ( void ) const { return _rb.size(); } - - Audio_Sequence * sequence ( void ) const; - Track * track ( void ) const; - - static void *disk_thread ( void *arg ); - - void _resize_buffers ( nframes_t nframes, int channels ); - -protected: - - void block_processed ( void ) { sem_post( &_blocks ); } - bool wait_for_block ( void ) - { - if ( _terminate ) - return false; - - while ( ! sem_wait( &_blocks ) && errno == EINTR ) - {} - - return ! _terminate; - } - - virtual void disk_thread ( void ) = 0; - - void base_flush ( bool is_output ); - virtual void flush ( void ) = 0; - - void run ( void ); - void detach ( void ); - -public: - - void shutdown ( void ); - - /* must be set before any Disk_Streams are created */ - static float seconds_to_buffer; - static size_t disk_io_kbytes; - - int xruns ( void ) { return _xruns; } - - Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ); - - virtual ~Disk_Stream ( ); - - void resize_buffers ( nframes_t nframes ); - -/* void seek ( nframes_t frame ); */ -/* bool seek_pending ( void ); */ - - virtual nframes_t process ( nframes_t nframes ) = 0; - - virtual int buffer_percent ( void ); - -}; diff --git a/timeline/src/Engine/Engine.C b/timeline/src/Engine/Engine.C deleted file mode 100644 index 3f7c84a..0000000 --- a/timeline/src/Engine/Engine.C +++ /dev/null @@ -1,247 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Engine.H" -#include "../Transport.H" - -#include "../Timeline.H" // for process() -#include "../Sequence_Widget.H" // for BBT and position info. - -/* This is the home of the JACK process callback */ - -#include "const.h" -#include "debug.h" -#include "Thread.H" - - - -Engine::Engine ( ) : _thread( "RT" ) -{ - _buffers_dropped = 0; - - DMESSAGE( "Creating audio I/O engine" ); -} - -Engine::~Engine ( ) -{ - DMESSAGE( "Deleting engine" ); - /* We have to deactivate here in order to avoid our process - callback is being invoked after we're already destroyed, but - before the base class is */ - deactivate(); -} - - - -/*************/ -/* Callbacks */ -/*************/ - -/* THREAD: RT */ -/** This is the jack xrun callback */ -int -Engine::xrun ( void ) -{ - return 0; -} - -/* THREAD: RT */ -void -Engine::freewheel ( bool starting ) -{ - if ( starting ) - DMESSAGE( "entering freewheeling mode" ); - else - DMESSAGE( "leaving freewheeling mode" ); -} - -/* THREAD: RT (non-RT) */ -int -Engine::buffer_size ( nframes_t nframes ) -{ - timeline->resize_buffers( nframes ); - - return 0; -} - -nframes_t -Engine::playback_latency ( void ) const -{ -#ifdef HAVE_JACK_PORT_GET_LATENCY_RANGE - jack_latency_range_t range; - - jack_port_get_latency_range( jack_port_by_name( jack_client(), "system:playback_1" ), - JackPlaybackLatency, - &range ); - - return range.min; -#else - return jack_port_get_latency( jack_port_by_name( jack_client(), "system:playback_1" ) ); -#endif -} - -/* THREAD: RT */ -/** This is the jack slow-sync callback. */ -int -Engine::sync ( jack_transport_state_t state, jack_position_t *pos ) -{ - static bool seeking = false; - - switch ( state ) - { - case JackTransportStopped: /* new position requested */ - /* JACK docs lie. This is only called when the transport - is *really* stopped, not when starting a slow-sync - cycle */ - transport->frame = pos->frame; - return 1; - case JackTransportStarting: /* this means JACK is polling slow-sync clients */ - { - if ( ! seeking ) - { - request_locate( pos->frame ); - seeking = true; - } - - bool r = true; - - if ( timeline ) - r = timeline->seek_pending(); - - if ( ! r ) - seeking = false; - - return ! seeking; - } - case JackTransportRolling: /* JACK's timeout has expired */ - /* FIXME: what's the right thing to do here? */ -// request_locate( pos->frame ); - return 1; -// return transport->frame == pos->frame; - break; - default: - printf( "unknown transport state.\n" ); - } - - return 0; -} - -/* THREAD: RT */ -void -Engine::timebase ( jack_transport_state_t, jack_nframes_t, jack_position_t *pos, int ) -{ - position_info pi = timeline->solve_tempomap( pos->frame ); - - pos->valid = JackPositionBBT; - - pos->beats_per_bar = pi.beats_per_bar; - pos->beat_type = pi.beat_type; - pos->beats_per_minute = pi.tempo; - - pos->bar = pi.bbt.bar + 1; - pos->beat = pi.bbt.beat + 1; - pos->tick = pi.bbt.tick; - pos->ticks_per_beat = 1920.0; /* FIXME: wrong place for this */ - - /* FIXME: fill this in */ - pos->bar_start_tick = 0; -} - -/* THREAD: RT */ -int -Engine::process ( nframes_t nframes ) -{ - /* FIXME: wrong place for this */ - _thread.set( "RT" ); - - transport->poll(); - - if ( !timeline) - /* handle chicken/egg problem */ - return 0; - - nframes_t n = 0; - - n += timeline->process_input(nframes); - n += timeline->process_output(nframes); - - if ( n != nframes * 2 ) - { - _buffers_dropped++; - WARNING("xrun"); - } - - /* if ( freewheeling() ) */ - /* { */ - /* if ( timeline ) */ - /* { */ - /* timeline->rdlock(); */ - - /* timeline->process( nframes ); */ - - /* timeline->unlock(); */ - /* } */ - /* } */ - /* else */ - /* { */ - /* if ( !timeline) */ - /* /\* handle chicken/egg problem *\/ */ - /* return 0; */ - - /* if ( timeline->tryrdlock() ) */ - /* { */ - /* /\* the data structures we need to access here (tracks and */ - /* * their ports, but not track contents) may be in an */ - /* * inconsistent state at the moment. Just punt and drop this */ - /* * buffer. *\/ */ - /* ++_buffers_dropped; */ - /* return 0; */ - /* } */ - - /* /\* this will initiate the process() call graph for the various */ - /* * number and types of tracks, which will in turn send data out */ - /* * the appropriate ports. *\/ */ - /* timeline->process( nframes ); */ - - /* timeline->unlock(); */ - /* } */ - - return 0; -} - - -/* TRHEAD: RT */ -void -Engine::thread_init ( void ) -{ - _thread.set( "RT" ); -} - -/* THREAD: RT */ -void -Engine::shutdown ( void ) -{ -} - -void -Engine::request_locate ( nframes_t frame ) -{ - if ( timeline ) - timeline->seek( frame ); -} diff --git a/timeline/src/Engine/Engine.H b/timeline/src/Engine/Engine.H deleted file mode 100644 index cf1d426..0000000 --- a/timeline/src/Engine/Engine.H +++ /dev/null @@ -1,72 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Mutex.H" - -class Port; - -#include "JACK/Client.H" - -#include "Thread.H" - -class Engine : public JACK::Client -{ - Thread _thread; /* only used for thread checking */ - - int _buffers_dropped; /* buffers dropped because of locking */ -/* int _buffers_dropped; /\* buffers dropped because of locking *\/ */ - - void shutdown ( void ); - int process ( nframes_t nframes ); - int sync ( jack_transport_state_t state, jack_position_t *pos ); - int xrun ( void ); - void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos ); - void freewheel ( bool yes ); - int buffer_size ( nframes_t nframes ); - void thread_init ( void ); - - Engine ( const Engine &rhs ); - Engine & operator = ( const Engine &rhs ); - - void request_locate ( nframes_t frame ); - -private: - - friend class Port; - friend class Transport; - -public: - - Engine ( ); - virtual ~Engine ( ); - - int dropped ( void ) const { return _buffers_dropped; } - - nframes_t system_latency ( void ) const { return nframes(); } - nframes_t playback_latency ( void ) const; - - float frames_to_milliseconds ( nframes_t frames ) - { - return ( frames * 1000 ) / (float)sample_rate(); - } -}; - -extern Engine * engine; diff --git a/timeline/src/Engine/Peak.H b/timeline/src/Engine/Peak.H deleted file mode 100644 index 8ee1529..0000000 --- a/timeline/src/Engine/Peak.H +++ /dev/null @@ -1,27 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -struct Peak { - float min; - float max; - - float normalization_factor ( void ) const; -} __attribute__ (( packed )); diff --git a/timeline/src/Engine/Peaks.C b/timeline/src/Engine/Peaks.C deleted file mode 100644 index 0fa4dd9..0000000 --- a/timeline/src/Engine/Peaks.C +++ /dev/null @@ -1,980 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -/* - peakfile reading/writing. -*/ - -/* Code for peakfile reading, resampling, generation and streaming */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Audio_File.H" -#include "Peaks.H" - -#include "assert.h" -#include "const.h" -#include "debug.h" -#include "Thread.H" -#include "file.h" - -#include - -#include -#include -using std::min; -using std::max; - -#include - -#include - - -struct peak_thread_data -{ - void(*callback)(void*); - void *userdata; - Peaks *peaks; -}; - - - - -/* whether to cache peaks at multiple resolutions on disk to - * drastically improve performance */ -bool Peaks::mipmapped_peakfiles = true; - -const int Peaks::cache_minimum = 256; /* minimum chunksize to build peakfiles for */ -const int Peaks::cache_levels = 8; /* number of sampling levels in peak cache */ -const int Peaks::cache_step = 1; /* powers of two between each level. 4 == 256, 2048, 16384, ... */ - -Peaks::peakbuffer Peaks::_peakbuf; - - - -static -char * -peakname ( const char *filename ) -{ - char *file; - - asprintf( &file, "%s.peak", filename ); - - return file; -} - - - - -struct peakfile_block_header -{ - uint32_t chunksize; - uint32_t skip; -} __attribute__ (( packed )); - -class Peakfile -{ - - FILE *_fp; - nframes_t _chunksize; - int _channels; /* number of channels this peakfile represents */ - off_t _offset; - - struct block_descriptor - { - nframes_t chunksize; - off_t pos; - - block_descriptor ( nframes_t chunksize, off_t pos ) : chunksize( chunksize ), pos( pos ) - { - } - - bool operator< ( const block_descriptor &rhs ) - { - return chunksize < rhs.chunksize; - } - }; - - std::list blocks; - -public: - - int nblocks ( void ) const - { - return blocks.size(); - } - - Peakfile ( ) - { - _fp = NULL; - _offset = 0; - _chunksize = 0; - _channels = 0; - } - - ~Peakfile ( ) - { - if ( _fp ) - close(); - } - - void rescan ( void ) - { - blocks.clear(); - } - - /* int blocks ( void ) const { return blocks.size(); } */ - /** find the best block for /chunksize/ */ - void - scan ( nframes_t chunksize ) - { - if ( ! blocks.size() ) - { - rewind( _fp ); - clearerr( _fp ); - - /* scan all blocks */ - for ( ;; ) - { - peakfile_block_header bh; - - fread( &bh, sizeof( bh ), 1, _fp ); - - if ( feof( _fp ) ) - break; - - DMESSAGE( "Peakfile: chunksize=%lu, skip=%lu", (uint64_t)bh.chunksize, (uint64_t) bh.skip ); - - ASSERT( bh.chunksize, "Chucksize of zero. Invalid peak file structure!" ); - - blocks.push_back( block_descriptor( bh.chunksize, ftello( _fp ) ) ); - - if ( ! bh.skip ) - /* last block */ - break; - - if ( fseeko( _fp, bh.skip, SEEK_CUR ) ) - { - WARNING( "seek failed: %s (%lu)", strerror( errno ), bh.skip ); - break; - } - } - } - - if ( ! blocks.size() ) - FATAL( "Peak file contains no blocks!" ); - - blocks.sort(); - - /* fall back on the smallest chunksize */ - fseeko( _fp, blocks.front().pos, SEEK_SET ); - _chunksize = blocks.front().chunksize; - - /* search for the best-fit chunksize */ - for ( std::list ::const_reverse_iterator i = blocks.rbegin(); - i != blocks.rend(); ++i ) - if ( chunksize >= i->chunksize ) - { - _chunksize = i->chunksize; - fseeko( _fp, i->pos, SEEK_SET ); - break; - } - -// DMESSAGE( "using peakfile block for chunksize %lu", _chunksize ); - _offset = ftello( _fp ); - } - - /** convert frame number of peak number */ - nframes_t frame_to_peak ( nframes_t frame ) - { - return ( frame / _chunksize ) * (nframes_t)_channels; - } - - /** return the number of peaks in already open peakfile /fp/ */ - nframes_t - npeaks ( void ) const - { - struct stat st; - - fstat( fileno( _fp ), &st ); - - return ( st.st_size - sizeof( peakfile_block_header ) ) / sizeof( Peak ); - } - - /** returns true if the peakfile contains /npeaks/ peaks starting at sample /s/ */ - bool - ready ( nframes_t start, nframes_t npeaks ) - { - if ( blocks.size() > 1 ) - return true; - else - return this->npeaks() > frame_to_peak( start ) + npeaks; - } - - /** given soundfile name /name/, try to open the best peakfile for /chunksize/ */ - bool - open ( const char *name, int channels, nframes_t chunksize ) - { - assert( ! _fp ); -// _chunksize = 0; - _channels = channels; - - char *pn = peakname( name ); - - if ( ! ( _fp = fopen( pn, "r" ) ) ) - { - WARNING( "Failed to open peakfile for reading: %s", strerror(errno) ); - free( pn ); - return false; - } - - free( pn ); - - scan( chunksize ); - - assert( _chunksize ); - - return true; - } - - bool - open ( FILE *fp, int channels, nframes_t chunksize ) - { - assert( ! _fp ); - - _fp = fp; - _chunksize = 0; - _channels = channels; - - scan( chunksize ); - - assert( _chunksize ); - - return true; - } - - void - leave_open ( void ) - { - _fp = NULL; - } - - void - close ( void ) - { - fclose( _fp ); - _fp = NULL; - } - - /** read /npeaks/ peaks at /chunksize/ starting at sample /s/ - * assuming the peakfile contains data for /channels/ - * channels. Place the result in buffer /peaks/, which must be - * large enough to fit the entire request. Returns the number of - * peaks actually read, which may be fewer than were requested. */ - nframes_t - read_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) - { - if ( ! _fp ) - { - DMESSAGE( "No peakfile open, WTF?" ); - return 0; - } - - const unsigned int ratio = chunksize / _chunksize; - - /* locate to start position */ - - if ( fseeko( _fp, _offset + ( frame_to_peak( s ) * sizeof( Peak ) ), SEEK_SET ) ) - { - DMESSAGE( "failed to seek... peaks not ready?" ); - return 0; - } - - if ( feof( _fp ) ) - return 0; - - if ( ratio == 1 ) - return fread( peaks, sizeof( Peak ) * _channels, npeaks, _fp ); - - Peak *pbuf = new Peak[ ratio * _channels ]; - - nframes_t len = 0; - - nframes_t i; - - for ( i = 0; i < npeaks; ++i ) - { - /* read in a buffer */ - len = fread( pbuf, sizeof( Peak ) * _channels, ratio, _fp ); - - Peak *pk = peaks + (i * _channels); - - /* get the peak for each channel */ - for ( int j = 0; j < _channels; ++j ) - { - Peak *p = &pk[ j ]; - - p->min = 0; - p->max = 0; - - const Peak *pb = pbuf + j; - - for ( int k = len; k--; pb += _channels ) - { - if ( pb->max > p->max ) - p->max = pb->max; - if ( pb->min < p->min ) - p->min = pb->min; - } - - } - - if ( feof( _fp) || len < ratio ) - break; - } - - delete[] pbuf; - - return i; - } -}; - - - -Peaks::Peaks ( Audio_File *c ) -{ - _rescan_needed = false; - _first_block_pending = false; - _mipmaps_pending = false; - _clip = c; - _peak_writer = NULL; - _peakfile = new Peakfile(); -} - -Peaks::~Peaks ( ) -{ - if ( _peak_writer ) - { - delete _peak_writer; - _peak_writer = NULL; - } - - delete _peakfile; - _peakfile = NULL; -} - - - -/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be - * called before any calls to operator[] */ -int -Peaks::fill_buffer ( float fpp, nframes_t s, nframes_t e ) const -{ - _fpp = fpp; - - return read_peaks( s, (e - s) / fpp, fpp ); -} - - -bool -Peaks::ready ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const -{ - if ( ! _peakfile->open( _clip->filename(), _clip->channels(), chunksize ) ) - return false; - - int r = _peakfile->ready( s, npeaks ); - - _peakfile->close(); - - return r; -} - -/** If this returns false, then the peakfile needs to be built */ -bool -Peaks::peakfile_ready ( void ) const -{ - if ( _rescan_needed ) - { - DMESSAGE( "Rescanning peakfile" ); - _peakfile->rescan(); - if ( _peakfile->open( _clip->filename(), _clip->channels(), 256 ) ) - _peakfile->close(); - - _rescan_needed = false; - } - - return _first_block_pending || current(); -} - -/** start building peaks and/or peak mipmap in another thread. It is - * safe to call this again before the thread finishes. /callback/ will - * be called with /userdata/ FROM THE PEAK BUILDING THREAD when the - * peaks are finished. */ -void -Peaks::make_peaks_asynchronously ( void(*callback)(void*), void *userdata ) const -{ - if ( _clip->dummy() ) - return; - - /* already working on it... */ - if( _first_block_pending || _mipmaps_pending ) - return; - - /* maybe still building mipmaps... */ - _first_block_pending = _peakfile->nblocks() < 1; - _mipmaps_pending = _peakfile->nblocks() <= 1; - - peak_thread_data *pd = new peak_thread_data(); - - pd->callback = callback; - pd->userdata = userdata; - pd->peaks = const_cast(this); - - _make_peaks_thread.clone( &Peaks::make_peaks, pd ); - _make_peaks_thread.detach(); - - DMESSAGE( "Starting new peak building thread" ); -} - -nframes_t -Peaks::read_peakfile_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const -{ - if ( ! _peakfile->open( _clip->filename(), _clip->channels(), chunksize ) ) - { - DMESSAGE( "Failed to open peakfile!" ); - return 0; - } - - nframes_t l = _peakfile->read_peaks( peaks, s, npeaks, chunksize ); - - _peakfile->close(); - - return l; -} - -nframes_t -Peaks::read_source_peaks ( Peak *peaks, nframes_t npeaks, nframes_t chunksize ) const -{ - int channels = _clip->channels(); - - sample_t *fbuf = new sample_t[ chunksize * channels ]; - - off_t len; - - nframes_t i; - for ( i = 0; i < npeaks; ++i ) - { - /* read in a buffer */ - len = _clip->read( fbuf, -1, chunksize ); - - Peak *pk = peaks + (i * channels); - - /* get the peak for each channel */ - for ( int j = 0; j < channels; ++j ) - { - Peak &p = pk[ j ]; - - p.min = 0; - p.max = 0; - - for ( nframes_t k = j; k < len * channels; k += channels ) - { - if ( fbuf[ k ] > p.max ) - p.max = fbuf[ k ]; - if ( fbuf[ k ] < p.min ) - p.min = fbuf[ k ]; - } - - } - - if ( len < (nframes_t)chunksize ) - break; - } - - delete[] fbuf; - - return i; -} - -nframes_t -Peaks::read_source_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const -{ - _clip->seek( s ); - - return read_source_peaks( peaks, npeaks, chunksize ); -} - -nframes_t -Peaks::read_peaks ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const -{ - THREAD_ASSERT( UI ); /* because _peakbuf cache is static */ - -// printf( "reading peaks %d @ %d\n", npeaks, chunksize ); - - if ( _peakbuf.size < (nframes_t)( npeaks * _clip->channels() ) ) - { - _peakbuf.size = npeaks * _clip->channels(); -// printf( "reallocating peak buffer %li\n", _peakbuf.size ); - _peakbuf.buf = (peakdata*)realloc( _peakbuf.buf, sizeof( peakdata ) + (_peakbuf.size * sizeof( Peak )) ); - } - - _peakbuf.offset = s; - _peakbuf.buf->chunksize = chunksize; - - /* FIXME: use actual minimum chunksize from peakfile! */ - if ( chunksize < (nframes_t)cache_minimum ) - { - _peakbuf.len = read_source_peaks( _peakbuf.buf->data, s, npeaks, chunksize ); - } - else - { - _peakbuf.len = read_peakfile_peaks( _peakbuf.buf->data, s, npeaks, chunksize ); - } - - return _peakbuf.len; -} - -/** returns false if peak file for /filename/ is out of date */ -bool -Peaks::current ( void ) const -{ - char *pn = peakname( _clip->filename() ); - - bool b = newer( pn, _clip->filename() ); - - free( pn ); - - return b; -} - -/* thread entry point */ -void * -Peaks::make_peaks ( void *v ) -{ - peak_thread_data *pd = (peak_thread_data*)v; - - if ( pd->peaks->make_peaks() ) - { - if ( pd->callback ) - pd->callback( pd->userdata ); - - pd->peaks->_rescan_needed = true; - } - - delete pd; - - return NULL; -} - -bool -Peaks::needs_more_peaks ( void ) const -{ - return _peakfile->nblocks() <= 1 && ! ( _first_block_pending || _mipmaps_pending ); -} - -bool -Peaks::make_peaks ( void ) const -{ - Peaks::Builder pb( this ); - - /* make the first block */ - int b = pb.make_peaks(); - - _first_block_pending = false; - - b = pb.make_peaks_mipmap(); - - _mipmaps_pending = false; - - return b; -} - -/** return normalization factor for a single peak, assuming the peak - * represents a downsampling of the entire range to be normalized. */ -float -Peak::normalization_factor( void ) const -{ - float s; - - s = 1.0f / fabs( this->max ); - - if ( s * this->min < -1.0 ) - s = 1.0f / fabs( this->min ); - - return s; -} - -/* wrapper for peak writer */ -void -Peaks::prepare_for_writing ( void ) -{ - THREAD_ASSERT( Capture ); - - assert( ! _peak_writer ); - - char *pn = peakname( _clip->filename() ); - - _first_block_pending = true; - _peak_writer = new Peaks::Streamer( pn, _clip->channels(), cache_minimum ); - - free( pn ); -} - -void -Peaks::finish_writing ( void ) -{ - assert( _peak_writer ); - - delete _peak_writer; - _peak_writer = NULL; - - _first_block_pending = false; -} - -void -Peaks::write ( sample_t *buf, nframes_t nframes ) -{ - THREAD_ASSERT( Capture ); - - _peak_writer->write( buf, nframes ); -} - - - -/* - The Streamer is for streaming peaks from audio buffers to disk while - capturing. It works by accumulating a peak value across write() - calls. The Streamer can only generate peaks at a single - chunksize--additional cache levels must be appended after the - Streamer has finished. -*/ - -Peaks::Streamer::Streamer ( const char *filename, int channels, nframes_t chunksize ) -{ - _channels = channels; - _chunksize = chunksize; - _index = 0; - _fp = NULL; - - _peak = new Peak[ channels ]; - memset( _peak, 0, sizeof( Peak ) * channels ); - - if ( ! ( _fp = fopen( filename, "w" ) ) ) - { - FATAL( "could not open peakfile for streaming." ); - } - - peakfile_block_header bh; - - bh.chunksize = chunksize; - bh.skip = 0; - - fwrite( &bh, sizeof( bh ), 1, _fp ); - - fflush( _fp ); - fsync( fileno( _fp ) ); -} - -Peaks::Streamer::~Streamer ( ) -{ -/* fwrite( _peak, sizeof( Peak ) * _channels, 1, _fp ); */ - - fflush( _fp ); - - touch( fileno( _fp ) ); - - fsync( fileno( _fp ) ); - - fclose( _fp ); - - delete[] _peak; -} - -/** append peaks for samples in /buf/ to peakfile */ -void -Peaks::Streamer::write ( const sample_t *buf, nframes_t nframes ) -{ - while ( nframes ) - { - const nframes_t remaining = _chunksize - _index; - - if ( ! remaining ) - { - fwrite( _peak, sizeof( Peak ) * _channels, 1, _fp ); - - memset( _peak, 0, sizeof( Peak ) * _channels ); - - _index = 0; - } - - int processed = min( nframes, remaining ); - - for ( int i = _channels; i--; ) - { - Peak *p = _peak + i; - - const sample_t *f = buf + i; - - for ( int j = processed; j--; f += _channels ) - { - if ( *f > p->max ) - p->max = *f; - if ( *f < p->min ) - p->min = *f; - } - } - - _index += processed; - nframes -= processed; - } - - /* FIXME: shouldn't we just use write() instead? */ - fflush( _fp ); -} - - - -/* - The Builder is for generating peaks from imported or updated - sources, or when the peakfile is simply missing. -*/ - -void -Peaks::Builder::write_block_header ( nframes_t chunksize ) -{ - if ( last_block_pos ) - { - /* update previous block */ - off_t pos = ftello( fp ); - - fseeko( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); - - peakfile_block_header bh; - - fread( &bh, sizeof( bh ), 1, fp ); - - fseeko( fp, last_block_pos - sizeof( peakfile_block_header ), SEEK_SET ); -// fseeko( fp, 0 - sizeof( bh ), SEEK_CUR ); - -// DMESSAGE( "old block header: chunksize=%lu, skip=%lu", (unsigned long) bh.chunksize, (unsigned long) bh.skip ); - - bh.skip = pos - last_block_pos; - - ASSERT( bh.skip, "Attempt to create empty block. pos=%lu, last_block_pos=%lu", pos, last_block_pos ); - -// DMESSAGE( "new block header: chunksize=%lu, skip=%lu", (unsigned long) bh.chunksize, (unsigned long) bh.skip ); - - fwrite( &bh, sizeof( bh ), 1, fp ); - - fseeko( fp, pos, SEEK_SET ); - } - - peakfile_block_header bh; - - bh.chunksize = chunksize; - bh.skip = 0; - - fwrite( &bh, sizeof( bh ), 1, fp ); - - last_block_pos = ftello( fp ); - - fflush( fp ); -} - -/** generate additional cache levels for a peakfile with only 1 block (ie. that of a new capture) */ -bool -Peaks::Builder::make_peaks_mipmap ( void ) -{ - if ( ! Peaks::mipmapped_peakfiles ) - return false; - - Audio_File *_clip = _peaks->_clip; - - const char *filename = _clip->filename(); - char *pn = peakname( filename ); - - FILE *rfp; - - if ( ! ( rfp = fopen( pn, "r" ) ) ) - { - WARNING( "could not open peakfile for reading: %s.", strerror( errno ) ); - free( pn ); - return false; - } - - { - peakfile_block_header bh; - - fread( &bh, sizeof( peakfile_block_header ), 1, rfp ); - - if ( bh.skip ) - { - WARNING( "Peakfile already has multiple blocks..." ); - fclose( rfp ); - free( pn ); - return false; - } - - } - - last_block_pos = sizeof( peakfile_block_header ); - - /* open for reading */ -// rfp = fopen( peakname( filename ), "r" ); - - /* open the file again for appending */ - if ( ! ( fp = fopen( pn, "r+" ) ) ) - { - WARNING( "could not open peakfile for appending: %s.", strerror( errno ) ); - free( pn ); - return false; - } - - free( pn ); - - if ( fseeko( fp, 0, SEEK_END ) ) - FATAL( "error performing seek: %s", strerror( errno ) ); - - if ( ftello( fp ) == sizeof( peakfile_block_header ) ) - { - DWARNING( "truncated peakfile. Programming error?" ); - return false; - } - - Peak buf[ _clip->channels() ]; - - /* now build the remaining peak levels, each based on the - * preceding level */ - - nframes_t cs = Peaks::cache_minimum << Peaks::cache_step; - - for ( int i = 1; i < Peaks::cache_levels; ++i, cs <<= Peaks::cache_step ) - { - DMESSAGE( "building level %d peak cache cs=%i", i + 1, cs ); - -/* DMESSAGE( "%lu", _clip->length() / cs ); */ - - if ( _clip->length() / cs < 1 ) - { - DMESSAGE( "source not long enough for any peaks at chunksize %lu", cs ); - break; - } - - Peakfile pf; - - /* open the peakfile for the previous cache level */ - - pf.open( rfp, _clip->channels(), cs >> Peaks::cache_step ); - -// pf.open( _clip->filename(), _clip->channels(), cs >> Peaks::cache_step ); - - write_block_header( cs ); - - off_t len; - nframes_t s = 0; - do { - len = pf.read_peaks( buf, s, 1, cs ); - - s += cs; - - fwrite( buf, sizeof( buf ), len, fp ); - } - while ( len > 0 && s < _clip->length() ); - - DMESSAGE( "Last sample was %lu", (unsigned long)s ); - - pf.leave_open(); - } - - fclose( rfp ); - fclose( fp ); - - DMESSAGE( "done" ); - - return true; -} - -bool -Peaks::Builder::make_peaks ( void ) -{ - Audio_File *_clip = _peaks->_clip; - - const char *filename = _clip->filename(); - - if ( _peaks->_peakfile && _peaks->_peakfile->nblocks() > 1 ) - { - /* this peakfile already has enough blocks */ - return false; - } - else - { - DMESSAGE( "building peaks for \"%s\"", filename ); - - char *pn = peakname( filename ); - - if ( ! ( fp = fopen( pn, "w+" ) ) ) - { - free( pn ); - return false; - } - - free( pn ); - - _clip->seek( 0 ); - - Peak buf[ _clip->channels() ]; - - DMESSAGE( "building level 1 peak cache" ); - - write_block_header( Peaks::cache_minimum ); - - /* build first level from source */ - off_t len; - do { - len = _peaks->read_source_peaks( buf, 1, Peaks::cache_minimum ); - - fwrite( buf, sizeof( buf ), len, fp ); - } - while ( len ); - - fclose( fp ); - - DMESSAGE( "done building peaks" ); - } - - return true; -} - -Peaks::Builder::Builder ( const Peaks *peaks ) : _peaks( peaks ) -{ - fp = NULL; - last_block_pos = 0; -} - - diff --git a/timeline/src/Engine/Peaks.H b/timeline/src/Engine/Peaks.H deleted file mode 100644 index c8d7612..0000000 --- a/timeline/src/Engine/Peaks.H +++ /dev/null @@ -1,159 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -#include "types.h" - -#include "Peak.H" - -#include - -#include "Thread.H" - - -class Audio_File; -class Peakfile; - -class Peaks -{ - /* true if first block is still being built */ - mutable volatile bool _first_block_pending; - mutable volatile bool _mipmaps_pending; - - mutable Thread _make_peaks_thread; - mutable Thread _make_peaks_mipmap_thread; - - static void * make_peaks_mipmap ( void *v ); - static void * make_peaks ( void *v ); - - struct peakdata { - - nframes_t chunksize; /* should always be a power of 2 */ - Peak data[]; - - }; - - struct peakbuffer { - - size_t size; /* total allocation size */ - size_t len; /* number of peaks */ - nframes_t offset; /* starting sample */ - - peakdata *buf; - - peakbuffer ( ) - { - size = len = 0; - } - }; - - Peakfile *_peakfile; - - class Streamer - { - FILE *_fp; - Peak *_peak; - int _chunksize; - int _channels; - int _index; - - /* not permitted */ - Streamer ( const Streamer &rhs ); - const Streamer &operator= ( const Streamer &rhs ); - - public: - - Streamer ( const char *filename, int channels, nframes_t chunksize ); - ~Streamer ( ); - - void write ( const sample_t *buf, nframes_t nframes ); - - }; - - class Builder - { - FILE *fp; - off_t last_block_pos; - const Peaks *_peaks; - - void write_block_header ( nframes_t chunksize ); - - public: - - bool make_peaks_mipmap ( void ); - bool make_peaks ( void ); - - Builder ( const Peaks *peaks ); - }; - - /* FIXME: Is this ever accessed by multiple threads? */ - static peakbuffer _peakbuf; - - Audio_File *_clip; - - mutable float _fpp; - - volatile mutable bool _rescan_needed; - - nframes_t read_peaks ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const; - nframes_t read_source_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const; - nframes_t read_source_peaks ( Peak *peaks, nframes_t npeaks, nframes_t chunksize ) const; - nframes_t read_peakfile_peaks ( Peak *peaks, nframes_t s, nframes_t npeaks, nframes_t chunksize ) const; - - Streamer * volatile _peak_writer; /* exists when streaming peaks to disk */ - - /* not permitted */ - Peaks ( const Peaks &rhs ); - const Peaks &operator= ( const Peaks &rhs ); - - bool current ( void ) const; - -public: - - static bool mipmapped_peakfiles; - - static const int cache_minimum; - static const int cache_levels; - static const int cache_step; - - Peaks ( Audio_File *c ); - ~Peaks ( ); - - Peak *peakbuf ( void ) const { return Peaks::_peakbuf.buf->data; } - void clip ( Audio_File *c ) { _clip = c; } - - int fill_buffer ( float fpp, nframes_t s, nframes_t e ) const; - - bool peakfile_ready ( void ) const; - - void read ( int X, float *hi, float *lo ) const; - bool ready ( nframes_t s, nframes_t npeaks, nframes_t chunksize ) const; - - bool make_peaks ( void ) const; - void make_peaks_asynchronously ( void(*callback)(void*), void *userdata ) const; - - void prepare_for_writing ( void ); - void finish_writing ( void ); - void write ( sample_t *buf, nframes_t nframes ); - - bool needs_more_peaks ( void ) const; -}; diff --git a/timeline/src/Engine/Playback_DS.C b/timeline/src/Engine/Playback_DS.C deleted file mode 100644 index e5cf15d..0000000 --- a/timeline/src/Engine/Playback_DS.C +++ /dev/null @@ -1,233 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -/* Handles streaming regions from disk to track outputs. */ - -/* FIXME: we shouldn't depend on these */ -#include "../Timeline.H" // for locking -#include "../Audio_Sequence.H" -#include "../Track.H" - -// #include "Port.H" -#include "Playback_DS.H" -#include "Engine.H" -#include "dsp.h" - -#include "const.h" -#include "debug.h" -#include "Thread.H" -#include - -bool -Playback_DS::seek_pending ( void ) -{ - return _pending_seek || buffer_percent() < 50; -} - -/** request that the IO thread perform a seek and rebuffer. This is - called for each Disk_Stream whenever the RT thread determines that - the transport has jumped to a new position. This is called *before* - process. */ -void -Playback_DS::seek ( nframes_t frame ) -{ - THREAD_ASSERT( RT ); - - /* FIXME: non-RT-safe IO */ - DMESSAGE( "requesting seek to frame %lu", (unsigned long)frame ); - - if ( seek_pending() ) - printf( "seek error, attempt to seek while seek is pending\n" ); - - _seek_frame = frame; - _pending_seek = true; - - /* wake the IO thread */ - block_processed(); -} - -/** set the playback delay to /frames/ frames. This be called prior to -a seek. */ -void -Playback_DS::undelay ( nframes_t delay ) -{ - _undelay = delay; -} - -/** read /nframes/ from the attached track into /buf/ */ -void -Playback_DS::read_block ( sample_t *buf, nframes_t nframes ) -{ - THREAD_ASSERT( Playback ); - - memset( buf, 0, nframes * sizeof( sample_t ) * channels() ); - -// printf( "IO: attempting to read block @ %lu\n", _frame ); - - if ( !timeline ) - return; - - while ( timeline->sequence_lock.tryrdlock() ) - { - if ( _terminate ) - return; - - usleep( 1000 * 10 ); - } - - if ( sequence() ) - { - if ( ! sequence()->play( buf, _frame + _undelay, nframes, channels() ) ) - WARNING( "Programming error?" ); - - _frame += nframes; - } - - timeline->sequence_lock.unlock(); -} - -void -Playback_DS::disk_thread ( void ) -{ - _thread.name( "Playback" ); - - DMESSAGE( "playback thread running" ); - - /* buffer to hold the interleaved data returned by the track reader */ - sample_t *buf = buffer_alloc( _nframes * channels() * _disk_io_blocks ); - sample_t *cbuf = buffer_alloc( _nframes ); - - const nframes_t nframes = _nframes; - nframes_t blocks_written; - - while ( ! _terminate ) - { - - seek: - - blocks_written = 0; - read_block( buf, nframes * _disk_io_blocks ); - - while ( blocks_written < _disk_io_blocks && - wait_for_block() ) - { -// lock(); // for seeking - - if ( _pending_seek ) - { - /* FIXME: non-RT-safe IO */ - DMESSAGE( "performing seek to frame %lu", (unsigned long)_seek_frame ); - - _frame = _seek_frame; - _pending_seek = false; - - flush(); - - goto seek; - } - - /* might have received terminate signal while waiting for block */ - if ( _terminate ) - goto done; - -// unlock(); // for seeking - - /* deinterleave the buffer and stuff it into the per-channel ringbuffers */ - - const size_t block_size = nframes * sizeof( sample_t ); - - for ( int i = 0; i < channels(); i++ ) - { - buffer_deinterleave_one_channel( cbuf, - buf + ( blocks_written * nframes * channels() ), - i, - channels(), - nframes ); - - while ( jack_ringbuffer_write_space( _rb[ i ] ) < block_size ) - usleep( 100 * 1000 ); - - jack_ringbuffer_write( _rb[ i ], ((char*)cbuf), block_size ); - } - - blocks_written++; - } - } - -done: - - DMESSAGE( "playback thread terminating" ); - - free(buf); - free(cbuf); - -// flush(); - - _terminate = false; -} - -/** take a single block from the ringbuffers and send it out the - * attached track's ports */ -nframes_t -Playback_DS::process ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - const size_t block_size = nframes * sizeof( sample_t ); - -// printf( "process: %lu %lu %lu\n", _frame, _frame + nframes, nframes ); - - for ( int i = channels(); i--; ) - { - void *buf = track()->output[ i ].buffer( nframes ); - - if ( engine->freewheeling() ) - { - /* only ever read nframes at a time */ - while ( jack_ringbuffer_read_space( _rb[i] ) < block_size ) - usleep( 10 * 1000 ); - - jack_ringbuffer_read( _rb[ i ], ((char*)buf), block_size ); - } - else - { - /* only ever read nframes at a time */ - if ( jack_ringbuffer_read_space( _rb[i] ) < block_size ) - { - ++_xruns; - memset( buf, 0, block_size ); - /* FIXME: we need to resync somehow */ - } - else - { - jack_ringbuffer_read( _rb[ i ], (char*)buf, block_size ); - } - } - - /* TODO: figure out a way to stop IO while muted without losing sync */ - if ( track()->mute() || ( Track::soloing() && ! track()->solo() ) ) - buffer_fill_with_silence( (sample_t*)buf, nframes ); - } - - block_processed(); - - /* FIXME: bogus */ - return nframes; -} diff --git a/timeline/src/Engine/Playback_DS.H b/timeline/src/Engine/Playback_DS.H deleted file mode 100644 index 128a745..0000000 --- a/timeline/src/Engine/Playback_DS.H +++ /dev/null @@ -1,51 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Disk_Stream.H" - -class Playback_DS : public Disk_Stream -{ - - void read_block ( sample_t *buf, nframes_t nframes ); - void disk_thread ( void ); - - void flush ( void ) { base_flush( true ); } - - volatile nframes_t _undelay; /* number of frames this diskstream - * should be undelayed by */ - -public: - - Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : - Disk_Stream( th, frame_rate, nframes, channels ) - { - _undelay = 0; - - run(); - } - - virtual ~Playback_DS ( ) { shutdown(); } - - bool seek_pending ( void ); - void seek ( nframes_t frame ); - nframes_t process ( nframes_t nframes ); - - void undelay ( nframes_t v ); - -}; diff --git a/timeline/src/Engine/Record_DS.C b/timeline/src/Engine/Record_DS.C deleted file mode 100644 index 312ce74..0000000 --- a/timeline/src/Engine/Record_DS.C +++ /dev/null @@ -1,382 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Handles streaming from track inputs to disk */ - -/* FIXME: we shouldn't depend on these */ -#include "../Timeline.H" // for locking -#include "../Audio_Sequence.H" -#include "../Track.H" - -// #include "Port.H" -#include "Record_DS.H" -#include "Engine.H" -#include "dsp.h" - -#include "const.h" -#include "debug.h" -#include "Thread.H" - -#include - -const Audio_Region * -Record_DS::capture_region ( void ) const -{ - if ( _capture ) - return _capture->region; - else - return NULL; -} - -Track::Capture * -Record_DS::capture ( void ) -{ - return _capture; -} - -/** write /nframes/ from buf to the capture file of the attached track */ -void -Record_DS::write_block ( sample_t *buf, nframes_t nframes ) -{ - THREAD_ASSERT( Capture ); - - /* stupid chicken/egg */ - if ( ! ( timeline && sequence() ) ) - return; - - if ( ! _capture ) - { - _capture = new Track::Capture; - - /* if ( ! _capture->audio_file ) */ - /* create the file */ - track()->record( _capture, _frame ); - } - - track()->write( _capture, buf, nframes ); - - _frames_written += nframes; -} - -void -Record_DS::disk_thread ( void ) -{ - _thread.name( "Capture" ); - - DMESSAGE( "capture thread running..." ); - - const nframes_t nframes = _nframes; - - _disk_io_blocks = 1; - - /* buffer to hold the interleaved data returned by the track reader */ - sample_t *buf = buffer_alloc( nframes * channels() * _disk_io_blocks ); - sample_t *cbuf = buffer_alloc( nframes ); - - _recording = true; - -// const size_t block_size = nframes * sizeof( sample_t ); - - nframes_t frames_read = 0; - - bool punching_in = false; - bool punching_out = false; - bool punched_in = false; - - nframes_t bS = 0; /* block start */ - nframes_t bE = 0; /* block end */ - -again: - - _capture = NULL; - - punched_in = false; - punching_out = false; - - nframes_t pS = _frame; /* punch start */ - nframes_t pE = _stop_frame; /* punch end */ - - if ( punching_in ) - { - /* write remainder of buffer */ - write_block( buf + ((pS - bS) * channels()), - bE - pS ); - - punching_in = false; - punched_in = true; - } - - while ( wait_for_block() ) - { - /* pull data from the per-channel ringbuffers and interlace it */ - size_t frames_to_read = nframes; - - /* we read the entire block if a partial... */ - for ( int i = 0; i < channels(); i++ ) - { - while ( jack_ringbuffer_read_space( _rb[ i ] ) < frames_to_read * sizeof( sample_t ) ) - usleep( 10 * 1000 ); - - jack_ringbuffer_read( _rb[ i ], ((char*)cbuf), frames_to_read * sizeof( sample_t ) ); - - buffer_interleave_one_channel( buf, - cbuf, - i, - channels(), - frames_to_read); - } - - bS = _first_frame + frames_read; - - frames_read += frames_to_read; - - bE = _first_frame + frames_read; - - if ( ! punched_in && bS > pS ) - { - /* we're supposed to be punching in but don't have data - until a later frame... write null data instead. FIXME: - it would probably be better to just have the record - threads running all the time so that there would always - have some actual data to write here */ - sample_t nbuf[bS - pS]; - memset(nbuf,0,bS - pS); - write_block(nbuf, pS - pS); - write_block(buf,frames_to_read); - punched_in = true; - punching_in = false; - } - else - { - punching_in = ! punched_in && bE > pS; - punching_out = punched_in && pE < bE; - - if ( punching_out ) - { - write_block( buf, - pE - bS ); - - break; - } - else if ( punching_in ) - { - assert( pS >= bS ); - assert( bE >= pS ); - - write_block( buf + ((pS - bS) * channels()), - bE - pS ); - - punching_in = false; - punched_in = true; - } - else if ( punched_in ) - { - write_block( buf, bE - bS ); - } - } - } - -// DMESSAGE( "capture thread terminating" ); - - /* flush what remains in the buffer out to disk */ - - /* { */ - /* while ( blocks_read-- > 0 || ( ! sem_trywait( &_blocks ) && errno != EAGAIN ) ) */ - /* { */ - /* for ( int i = channels(); i--; ) */ - /* { */ - /* jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); */ - - /* buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); */ - /* } */ - - /* const nframes_t frames_remaining = (_stop_frame - _frame ) - _frames_written; */ - - /* if ( frames_remaining < nframes ) */ - /* { */ - /* /\* this is the last block, might be partial *\/ */ - /* write_block( buf, frames_remaining ); */ - /* break; */ - /* } */ - /* else */ - /* write_block( buf, nframes ); */ - /* } */ - /* } */ - - - - if ( _capture ) - { - DMESSAGE( "finalzing capture" ); - Track::Capture *c = _capture; - - _capture = NULL; - - /* now finalize the recording */ - -// if ( c->audio_file ) - track()->finalize( c, _stop_frame ); - - delete c; - } - - if ( ! _terminate ) - { - nframes_t in, out; - - if ( timeline->next_punch( _stop_frame, &in, &out ) ) - { - _frame = in; - _stop_frame = out; - _frames_written = 0; - - punched_in = false; - punching_out = false; - - punching_in = bE > in; - - DMESSAGE( "Next punch: %lu:%lu", (unsigned long)in,(unsigned long)out ); - - goto again; - } - } - - free(buf); - free(cbuf); - - flush(); - - _terminate = false; - _recording = false; - - DMESSAGE( "capture thread gone" ); -} - - -/** begin recording */ -void -Record_DS::start ( nframes_t frame, nframes_t start_frame, nframes_t stop_frame ) -{ - THREAD_ASSERT( UI ); - - if ( _recording ) - { - WARNING( "programming error: attempt to start recording while recording is still in progress" ); - return; - } - -/* /\* FIXME: safe to do this here? *\/ */ -/* flush(); */ - - DMESSAGE( "recording started at frame %lu", (unsigned long)frame); - - _frame = start_frame; - _stop_frame = stop_frame ? stop_frame : JACK_MAX_FRAMES; - - _first_frame = frame; - - run(); -} - -/** finalize the recording process. */ -void -Record_DS::stop ( nframes_t frame ) -{ - THREAD_ASSERT( UI ); - - _stop_frame = frame; - - DMESSAGE( "recording stop scheduled" ); -} - - -#include "../Transport.H" -extern Transport *transport; - -/** read from the attached track's ports and stuff the ringbuffers */ -nframes_t -Record_DS::process ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - if ( ! ( _recording && _thread.running() ) ) - return 0; - - /* if ( transport->frame < _frame ) */ - /* return 0; */ - -/* DMESSAGE( "recording actually happening at %lu (start frame %lu)", (unsigned long)transport->frame, (unsigned long)_frame); */ - - nframes_t offset = 0; - -/* if ( _frame > transport->frame && */ -/* _frame < transport->frame + nframes ) */ -/* { */ -/* /\* The record start frame falls somewhere within the current */ -/* buffer. We must discard the unneeded portion and only */ -/* stuff the part requested into the ringbuffer. *\/ */ - -/* offset = _frame - transport->frame; */ - -/* /\* DMESSAGE( "offset = %lu", (unsigned long)offset ); *\/ */ -/* } */ - - const size_t offset_size = offset * sizeof( sample_t ); - const size_t block_size = ( nframes * sizeof( sample_t ) ) - offset_size; - - for ( int i = 0; i < channels(); i++ ) - { - /* read the entire input buffer */ - void *buf = track()->input[ i ].buffer( nframes ); - - if ( engine->freewheeling() ) - { - while ( _thread.running() && jack_ringbuffer_write_space( _rb[i] ) < block_size ) - usleep( 10 * 1000 ); - - if ( ! _thread.running() ) - return 0; - - jack_ringbuffer_write( _rb[ i ], ((char*)buf) + offset_size, block_size ); - } - else - { - if ( ! _thread.running() ) - return 0; - - if ( jack_ringbuffer_write_space( _rb[i] ) < block_size ) - { - memset( buf, 0, block_size ); - /* FIXME: we need to resync somehow */ - WARNING( "xrun" ); - ++_xruns; - } - - jack_ringbuffer_write( _rb[ i ], ((char*)buf) + offset_size, block_size ); - -// DMESSAGE( "wrote %lu", (unsigned long) nframes ); - - } - } - - block_processed(); - - /* FIXME: bogus */ - return nframes; -} diff --git a/timeline/src/Engine/Record_DS.H b/timeline/src/Engine/Record_DS.H deleted file mode 100644 index 054bbc6..0000000 --- a/timeline/src/Engine/Record_DS.H +++ /dev/null @@ -1,76 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Disk_Stream.H" - -#include "Audio_File_SF.H" -class Audio_File; -class Peak_Writer; - -class Record_DS : public Disk_Stream -{ - - /* not permitted */ - Record_DS ( const Record_DS &rhs ); - Record_DS & operator= ( const Record_DS &rhs ); - - Track::Capture *_capture; - - nframes_t _frames_written; - volatile nframes_t _stop_frame; - volatile nframes_t _first_frame; - - volatile bool _recording; - - Audio_File_SF *_af; /* capture file */ - - void write_block ( sample_t *buf, nframes_t nframes ); - void disk_thread ( void ); - - virtual void flush ( void ) { base_flush( false ); } - -public: - - Record_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : - Disk_Stream( th, frame_rate, nframes, channels ) - { - sem_destroy( &_blocks ); - sem_init( &_blocks, 0, 0 ); - - _capture = NULL; - _recording = false; - _stop_frame = JACK_MAX_FRAMES; - _frames_written = 0; - _first_frame = 0; - } - - virtual ~Record_DS ( ) { shutdown(); } - -/* bool seek_pending ( void ); */ -/* void seek ( nframes_t frame ); */ - const Audio_Region * capture_region ( void ) const; - Track::Capture * capture ( void ); - - void start ( nframes_t frame, nframes_t start_frame, nframes_t stop_frame = 0 ); - void stop ( nframes_t frame ); - nframes_t process ( nframes_t nframes ); - -}; diff --git a/timeline/src/Engine/Timeline.C b/timeline/src/Engine/Timeline.C deleted file mode 100644 index 9bcfa0f..0000000 --- a/timeline/src/Engine/Timeline.C +++ /dev/null @@ -1,362 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../Timeline.H" - -#include "../Transport.H" // for .rolling -#include "../Track.H" - -#include "Record_DS.H" -#include "Playback_DS.H" - -#include "Thread.H" -#include "../Cursor_Sequence.H" - -#include "Engine.H" - -#include - -/** Initiate recording for all armed tracks */ -bool -Timeline::record ( void ) -{ - THREAD_ASSERT( UI ); - - DMESSAGE( "Initiating recording." ); - - /* FIXME: right place for this? */ - - if ( transport->automatically_create_takes() && - ! _created_new_takes ) - { - DMESSAGE( "Creating new takes." ); - add_take_for_armed_tracks(); - _created_new_takes = true; - } - - deactivate(); - - Loggable::block_start(); - - nframes_t frame = transport->frame; - - nframes_t _punch_out_frame = 0; -// nframes_t _punch_in_frame = 0; - - if ( transport->punch_enabled() ) - { - DMESSAGE( "Finding next punch region following frame %lu...", (unsigned long)frame); - - const Sequence_Widget *p = punch_cursor_track->prev( frame ); - const Sequence_Widget *n = punch_cursor_track->next( frame ); - - if (p || n ) - { - if ( p && frame >= p->start() && frame < p->start() + p->length() ) - { - /* recording started in the middle of a punch - * cursor... Just start recording and punch out at the - * end of it */ - _punch_out_frame = p->start() + p->length(); - } - else if ( n && n->start() >= frame ) - { - /* recording started outside of a punch cursor, set - * punch in frame to beginning of next cursor */ - frame = n->start(); - _punch_out_frame = n->start() + n->length(); - } - - DMESSAGE( "Punch enabled... Range %lu:%lu", - (unsigned long)frame, - (unsigned long)_punch_out_frame); - } - } - -// _punch_in_frame = frame; - - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->record_ds ) - { - t->record_ds->start( transport->frame, frame, _punch_out_frame ); - } - } - - transport->recording = true; - - - return true; -} - -void -Timeline::punch_out ( nframes_t frame ) -{ - THREAD_ASSERT( UI ); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->record_ds ) - t->record_ds->stop( frame ); - } - - DMESSAGE( "Waiting for record threads to shutdown." ); - - /* none of the record threads need to call Fl::lock, because we're - * holding up the UI thread waiting for them to join.*/ - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->record_ds ) - t->record_ds->shutdown(); - } - - DMESSAGE( "All record threads stopped." ); -} - -/** stop recording for all armed tracks. Does not affect transport. */ -void -Timeline::stop ( void ) -{ - THREAD_ASSERT( UI ); - - nframes_t frame = transport->frame; - - /* if ( transport->punch_enabled() ) */ - /* { */ - /* const Sequence_Widget *w = punch_cursor_track->prev( frame ); */ - - /* if ( w && w->start() + w->length() < frame ) */ - /* frame = w->start() + w->length(); */ - /* } */ - - punch_out( frame ); - - Loggable::block_end(); - - activate(); - - transport->recording = false; -} - - -/**********/ -/* Engine */ -/**********/ - -nframes_t -Timeline::process_input ( nframes_t nframes ) -{ - - /* if ( engine->freewheeling() ) */ - /* { */ - /* rdlock(); */ - /* } */ - /* else */ - /* { */ - /* if ( tryrdlock() ) */ - /* return 0; */ - /* } */ - - if ( ! transport->recording ) - return nframes; - - /* we don't lock here in order to avoid deadlocks. we already know - * that only the record diskthread will be altering timeline - * structures during recording since the GUI is disabled. */ - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->process_input( nframes ); - } - - /* unlock(); */ - - return nframes; -} - -nframes_t -Timeline::process_output ( nframes_t nframes ) -{ - - /* if ( engine->freewheeling() ) */ - /* { */ - /* rdlock(); */ - /* } */ - /* else */ - /* { */ - /* if ( tryrdlock() ) */ - /* return 0; */ - /* } */ - - bool r = transport->recording || engine->freewheeling(); - - if ( ! r ) - if ( track_lock.tryrdlock() ) - return 0; -// rdlock(); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->process_output( nframes ); - } - - if ( ! r ) - track_lock.unlock(); - - return nframes; - -} - -void -Timeline::seek ( nframes_t frame ) -{ - THREAD_ASSERT( RT ); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->seek( frame ); - } -} - -/* THREAD: RT (non-RT) */ -void -Timeline::resize_buffers ( nframes_t nframes ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->resize_buffers( nframes ); - } -} - -/** return true if any playback stream's buffer is less than 50% full */ -bool -Timeline::seek_pending ( void ) -{ -// THREAD_ASSERT( RT ); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - if ( t->playback_ds->seek_pending() ) - return true; - } - - return false; -} - - -/* FIXME: shouldn't these belong to the engine? */ -int -Timeline::total_input_buffer_percent ( void ) -{ - int r = 0; - - int cnt = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->record_ds ) - { - ++cnt; - r += t->record_ds->buffer_percent(); - } - } - - if ( ! cnt ) - return 0; - - return r / cnt; -} - -int -Timeline::total_output_buffer_percent ( void ) -{ - - int r = 0; - - int cnt = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - { - ++cnt; - r += t->playback_ds->buffer_percent(); - } - } - - if ( ! cnt ) - return 0; - - return r / cnt; -} - -int -Timeline::total_playback_xruns ( void ) -{ - int r = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - r += t->playback_ds->xruns(); - } - - return r; -} - -int -Timeline::total_capture_xruns ( void ) -{ - int r = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->record_ds ) - r += t->record_ds->xruns(); - } - - return r; -} diff --git a/timeline/src/Engine/Track.C b/timeline/src/Engine/Track.C deleted file mode 100644 index 4bfdb5f..0000000 --- a/timeline/src/Engine/Track.C +++ /dev/null @@ -1,410 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "../Track.H" -#include "../Transport.H" // for rolling -#include "../Control_Sequence.H" - -#include "Playback_DS.H" -#include "Record_DS.H" -#include "Engine.H" - - - -/**********/ -/* Engine */ -/**********/ - -const Audio_Region * -Track::capture_region ( void ) const -{ - if ( record_ds ) - return record_ds->capture_region(); - else - return NULL; -} - -Track::Capture * -Track::capture ( void ) -{ - if ( record_ds ) - return record_ds->capture(); - else - return NULL; -} - -void -Track::update_port_names ( void ) -{ - for ( unsigned int i = 0; i < output.size(); ++i ) - { - output[ i ].trackname( name() ); - output[ i ].rename(); - } - - for ( unsigned int i = 0; i < input.size(); ++i ) - { - input[ i ].trackname( name() ); - input[ i ].rename(); - } -/* /\* tell any attached control sequences to do the same *\/ */ -/* for ( int i = control->children(); i-- ) */ -/* ((Control_Sequence*)control->child( i ))->update_port_names(); */ - -} - -bool -Track::configure_outputs ( int n ) -{ - int on = output.size(); - - if ( n == on ) - return true; - - DMESSAGE( "Reconfiguring outputs for track %s", name() ); - - if ( playback_ds ) - { - Playback_DS *ds = playback_ds; - playback_ds = NULL; - - delete ds; - } - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - char s[512]; - snprintf( s, sizeof(s), "out-%i", i + 1 ); - - JACK::Port p( engine, name(), s, JACK::Port::Output, JACK::Port::Audio ); - - p.terminal(true); - - if ( !p.activate() ) - { - FATAL( "could not created output port!"); - } - - if ( p.valid() ) - output.push_back( p ); - else - WARNING( "could not create output port!" ); - } - } - else - { - for ( int i = on; i > n; --i ) - { - output.back().shutdown(); - output.pop_back(); - } - } - - if ( output.size() ) - playback_ds = new Playback_DS( this, engine->sample_rate(), engine->nframes(), output.size() ); - - /* FIXME: bogus */ - return true; -} - -bool -Track::configure_inputs ( int n ) -{ - int on = input.size(); - - if ( n == on ) - return true; - - DMESSAGE( "Reconfiguring inputs for track %s", name() ); - -// engine->lock(); - - if ( record_ds ) - { - Record_DS *ds = record_ds; - record_ds = NULL; - - delete ds; - } - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - char s[512]; - snprintf( s, sizeof(s), "in-%i", i + 1 ); - - JACK::Port p( engine, name(), s, JACK::Port::Input, JACK::Port::Audio ); - - p.terminal( true ); - - if ( !p.activate() ) - { - FATAL( "could not created output port!"); - } - - if ( p.valid() ) - input.push_back( p ); - else - WARNING( "could not create input port!" ); - } - } - else - { - for ( int i = on; i > n; --i ) - { - input.back().shutdown(); - input.pop_back(); - } - } - - if ( input.size() ) - record_ds = new Record_DS( this, engine->sample_rate(), engine->nframes(), input.size() ); - -// engine->unlock(); - - /* FIXME: bogus */ - return true; -} - -nframes_t -Track::process_input ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - if ( ! transport->rolling ) - { - /* There is no work to do when we're not rolling. */ - - return 0; - } - - if ( record_ds ) - return record_ds->process( nframes ); - else - return 0; - -} - -nframes_t -Track::process_output ( nframes_t nframes ) -{ - THREAD_ASSERT( RT ); - - if ( ! transport->rolling ) - { - for ( int i = output.size(); i--; ) - output[ i ].silence( nframes ); - - return 0; - } - - /* FIXME: should we blank the control output here or leave it floating? */ - for ( int i = 0; i < ((Fl_Pack*)control)->children(); i++ ) - ((Control_Sequence*)((Fl_Pack*)control)->child( i ))->process( nframes ); - - if ( playback_ds ) - return playback_ds->process( nframes ); - else - return 0; -} - - - -void -Track::seek ( nframes_t frame ) -{ - THREAD_ASSERT( RT ); - - compute_latency_compensation(); - - if ( playback_ds ) - return playback_ds->seek( frame ); -} - -void -Track::undelay ( nframes_t nframes ) -{ -// THREAD_ASSERT( RT ); - - if ( playback_ds ) - playback_ds->undelay( nframes ); -} - -/* THREAD: RT (non-RT) */ -void -Track::resize_buffers ( nframes_t nframes ) -{ - if ( record_ds ) - record_ds->resize_buffers( nframes ); - if ( playback_ds ) - playback_ds->resize_buffers( nframes ); -} - -#include - -static unsigned long uuid_counter = 0; - -/** very cheap UUID generator... */ -unsigned long long -uuid ( void ) -{ - time_t t = time( NULL ); - - return (unsigned long long) t + uuid_counter++; -} - -/** create capture region and prepare to record */ -void -Track::record ( Capture *c, nframes_t frame ) -{ - THREAD_ASSERT( Capture ); - - char *pat; - - asprintf( &pat, "%s-%llu", name(), uuid() ); - - c->audio_file = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format ); - - free( pat ); - - if ( ! c->audio_file ) - FATAL( "Could not create file for new capture!" ); - - /* open it again for reading in the GUI thread */ - // Audio_File *af = Audio_File::from_file( c->audio_file->name() ); - /* must acquire the FLTK lock because adding a widget might interfere with drawing */ -// Fl::lock(); - - /* must acquire a write lock because the Audio_Region constructor - * will add the region to the specified sequence, which might affect playback */ - - timeline->sequence_lock.wrlock(); - - c->region = new Audio_Region( c->audio_file, sequence(), frame ); - - timeline->sequence_lock.unlock(); - -// Fl::unlock(); - - c->region->prepare(); - - nframes_t min,max; - - input[0].get_latency( JACK::Port::Input, &min, &max ); - - if ( transport->freewheel_enabled() ) - { - /* in freewheeling mode, assume we're bouncing and only - * compensate for capture latency */ - _capture_offset = max; - - /* FIXME: hack to compensate for jack 1 period delay when looped back */ -// _capture_offset += engine->playback_latency() / 2; - _capture_offset += engine->nframes(); - } - else - { - /* not freewheeling, so assume we're overdubbing and need to - * compensate for both capture and playback latency */ - _capture_offset = max; - - /* since the track output might not be connected to - * anything, just get the playback latency */ - /* When playback latency compensation is enabled, this will - * have already been done. */ - if ( ! Timeline::playback_latency_compensation ) - _capture_offset += engine->playback_latency(); - } -} - -/** write a block to the (already opened) capture file */ -void -Track::write ( Capture *c, sample_t *buf, nframes_t nframes ) -{ - THREAD_ASSERT( Capture ); - - nframes_t l = c->audio_file->write( buf, nframes ); - - c->region->write( l ); -} - -#include - -void -Track::finalize ( Capture *c, nframes_t frame ) -{ - THREAD_ASSERT( Capture ); - - /* adjust region start for latency */ - /* FIXME: is just looking at the first channel good enough? */ - - DMESSAGE( "finalizing audio file" ); - c->audio_file->finalize(); - - DMESSAGE( "Adjusting capture by %lu frames.", (unsigned long)_capture_offset ); - - timeline->sequence_lock.wrlock(); - - c->region->offset( _capture_offset ); - - timeline->sequence_lock.unlock(); - - _capture_offset = 0; - - /* have to do this last, as it logs the create */ - c->region->finalize( frame ); -} - -void -Track::compute_latency_compensation ( void ) -{ - if ( Timeline::playback_latency_compensation && output.size() ) - { - nframes_t tmin,tmax; - - tmin = JACK_MAX_FRAMES >> 1; - tmax = 0; - - for ( unsigned int i = 0; i < output.size(); i++ ) - { - nframes_t min,max; - output[i].get_latency( JACK::Port::Output, &min, &max ); - - if ( max > tmax ) - tmax = max; - if ( min < tmin ) - tmin = min; - } - - DMESSAGE( "Track %s, setting undelay to %lu", name(), (unsigned long)tmax); - char s[256]; - snprintf( s, sizeof(s), "Latency Comp: -%lu", (unsigned long)tmax); - - copy_tooltip(s); - - undelay( tmax ); - } - else - { - undelay( 0 ); - } -} diff --git a/timeline/src/Engine/const.h b/timeline/src/Engine/const.h deleted file mode 100644 index 623ca48..0000000 --- a/timeline/src/Engine/const.h +++ /dev/null @@ -1,20 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#define __MODULE__ "non-timeline:engine" diff --git a/timeline/src/Engine/types.h b/timeline/src/Engine/types.h deleted file mode 100644 index cd3cc2c..0000000 --- a/timeline/src/Engine/types.h +++ /dev/null @@ -1,25 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -typedef jack_nframes_t nframes_t; -typedef float sample_t; diff --git a/timeline/src/NSM.C b/timeline/src/NSM.C deleted file mode 100644 index 28c702f..0000000 --- a/timeline/src/NSM.C +++ /dev/null @@ -1,119 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "const.h" -#include "debug.h" -#include "Timeline.H" -#include "TLE.H" -#include "Project.H" -#include "OSC/Endpoint.H" - -#include - -#define OSC_INTERVAL 0.2f - -extern char *instance_name; -extern Timeline *timeline; - -// extern NSM_Client *nsm; - - - -static int -command_save ( char **out_msg, void *userdata ) -{ - if ( timeline->command_save() ) - return ERR_OK; - else - { - *out_msg = strdup( "Failed to save for unknown reason"); - return ERR_GENERAL; - } -} - -static int -command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg, void *userdata ) -{ - if ( instance_name ) - free( instance_name ); - - instance_name = strdup( client_id ); - - timeline->osc->name( client_id ); - - int r = 0; - - if ( Project::validate( name ) ) - { - if ( timeline->command_load( name, display_name ) ) - r = ERR_OK; - else - { - *out_msg = strdup( "Failed to load for unknown reason" ); - r = ERR_GENERAL; - } - } - else - { - if ( timeline->command_new( name, display_name ) ) - r =ERR_OK; - else - { - *out_msg = strdup( "Failed to load for unknown reason" ); - r = ERR_GENERAL; - } - } - - timeline->say_hello(); - -// timeline->connect_osc(); - - return r; -} - -static void -command_session_is_loaded ( void *userdata ) -{ - MESSAGE( "NSM says session is loaded." ); -} - -static int -command_broadcast ( const char *path, lo_message msg, void *userdata ) -{ - lo_message_get_argc( msg ); -// lo_arg **argv = lo_message_get_argv( msg ); - - if ( !strcmp( path, "/non/hello" ) ) - { - timeline->handle_hello( msg ); - return 0; - } - else - return -1; - -} - -void -set_nsm_callbacks ( nsm_client_t *nsm ) -{ - nsm_set_open_callback( nsm, command_open, 0 ); - nsm_set_save_callback( nsm, command_save, 0 ); - nsm_set_broadcast_callback( nsm, command_broadcast, 0 ); - nsm_set_session_is_loaded_callback( nsm, command_session_is_loaded, 0 ); -} diff --git a/timeline/src/OSC_Thread.C b/timeline/src/OSC_Thread.C deleted file mode 100644 index 70fe6fe..0000000 --- a/timeline/src/OSC_Thread.C +++ /dev/null @@ -1,94 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "OSC_Thread.H" - -#include "Timeline.H" - -#include -#include - -#include "debug.h" - -#include "OSC/Endpoint.H" - -extern Timeline *timeline; - -OSC_Thread::OSC_Thread ( ) -{ - // _thread.init(); - _shutdown = false; -} - -OSC_Thread::~OSC_Thread ( ) -{ - lock(); - if ( _shutdown == false ) - { - _shutdown = true; - _thread.join(); - } - unlock(); -} - - -void -OSC_Thread::start ( ) -{ - _thread.clone( &OSC_Thread::process, this ); -} - -void -OSC_Thread::join ( ) -{ - _thread.join(); -} - -void -OSC_Thread::process ( void ) -{ - _thread.name( "OSC" ); - - DMESSAGE( "OSC Thread starting" ); - - while ( !_shutdown ) - { - if ( trylock() ) - { - timeline->osc->check(); - timeline->process_osc(); - unlock(); - } - - usleep( 50 * 1000 ); - } - - DMESSAGE( "OSC Thread stopping." ); -} - -void * -OSC_Thread::process ( void *v ) -{ - OSC_Thread *t = (OSC_Thread*)v; - - t->process(); - - return NULL; -} - diff --git a/timeline/src/OSC_Thread.H b/timeline/src/OSC_Thread.H deleted file mode 100644 index d678028..0000000 --- a/timeline/src/OSC_Thread.H +++ /dev/null @@ -1,42 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2012 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Thread.H" -#include "Mutex.H" - -class OSC_Thread : public Mutex -{ - Thread _thread; /* io thread */ - - volatile bool _shutdown; - -public: - - OSC_Thread ( ); - - virtual ~OSC_Thread ( ); - - void join ( void ); - void shutdown ( void ) { _shutdown = true; } - void start ( void ); - void process ( void ); - static void *process ( void * ); -}; diff --git a/timeline/src/Project.C b/timeline/src/Project.C deleted file mode 100644 index f92375f..0000000 --- a/timeline/src/Project.C +++ /dev/null @@ -1,404 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Routings for opening/closing/creation of projects. All the actual - project state belongs to Timeline and other classes. */ - -/* Project management routines. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "Loggable.H" -#include "Project.H" - -#include "Timeline.H" // for sample_rate() -#include "Engine/Engine.H" // for sample_rate() -#include "TLE.H" // all this just for load and save... - -#include - -#include "const.h" -#include "debug.h" -#include "file.h" -#include "Block_Timer.H" - -#include "Transport.H" - -extern Transport *transport; -extern TLE *tle; - -const int PROJECT_VERSION = 2; - -extern char *instance_name; - - - -const char *Project::_errstr[] = -{ - "Not a Non-DAW project", - "Locked by another process", - "Access denied", - "Samplerate mismatch", - "Incompatible project version" -}; - -char Project::_name[256]; -char Project::_created_on[40]; -char Project::_path[512]; -bool Project::_is_open = false; -int Project::_lockfd = 0; - - - -/***********/ -/* Private */ -/***********/ - -void -Project::set_name ( const char *name ) -{ - strcpy( Project::_name, name ); - - if ( Project::_name[ strlen( Project::_name ) - 1 ] == '/' ) - Project::_name[ strlen( Project::_name ) - 1 ] = '\0'; - - char *s = rindex( Project::_name, '/' ); - - s = s ? s + 1 : Project::_name; - - memmove( Project::_name, s, strlen( s ) + 1 ); - - for ( s = Project::_name; *s; ++s ) - if ( *s == '_' || *s == '-' ) - *s = ' '; -} - -bool -Project::write_info ( void ) -{ - FILE *fp; - - if ( ! ( fp = fopen( "info", "w" ) ) ) - { - WARNING( "could not open project info file for writing." ); - return false; - } - - char s[40]; - - if ( ! *_created_on ) - { - time_t t = time( NULL ); - ctime_r( &t, s ); - s[ strlen( s ) - 1 ] = '\0'; - } - else - strcpy( s, _created_on ); - - fprintf( fp, "created by\n\t%s %s\ncreated on\n\t%s\nversion\n\t%d\nsample rate\n\t%lu\n", - APP_NAME, VERSION, - s, - PROJECT_VERSION, - (unsigned long)timeline->sample_rate() ); - - fclose( fp ); - - return true; -} - -void -Project::undo ( void ) -{ - Loggable::undo(); -} - -bool -Project::read_info ( int *version, nframes_t *sample_rate, char **creation_date, char **created_by ) -{ - FILE *fp; - - if ( ! ( fp = fopen( "info", "r" ) ) ) - { - WARNING( "could not open project info file for reading." ); - return false; - } - - *version = 0; - *sample_rate = 0; - *creation_date = 0; - *created_by = 0; - - char *name, *value; - - while ( fscanf( fp, "%m[^\n]\n\t%m[^\n]\n", &name, &value ) == 2 ) - { - MESSAGE( "Info: %s = %s", name, value ); - - if ( ! strcmp( name, "sample rate" ) ) - *sample_rate = atoll( value ); - else if ( ! strcmp( name, "version" ) ) - *version = atoi( value ); - else if ( ! strcmp( name, "created on" ) ) - *creation_date = strdup( value ); - else if ( ! strcmp( name, "created by" ) ) - *created_by = strdup( value ); - - free( name ); - free( value ); - } - - fclose( fp ); - - return true; -} - -/**********/ -/* Public */ -/**********/ - -/** Save out any settings and unjournaled state... */ -bool -Project::save ( void ) -{ - if ( ! open() ) - return true; - - tle->save_timeline_settings(); - - return Loggable::save_unjournaled_state(); -} - - -/** Close the project (reclaiming all memory) */ -bool -Project::close ( void ) -{ - if ( ! open() ) - return true; - - if ( ! save() ) - return false; - - Loggable::close(); - -// write_info(); - - _is_open = false; - - *Project::_name = '\0'; - *Project::_created_on = '\0'; - - release_lock( &_lockfd, ".lock" ); - - delete engine; - engine = NULL; - - return true; -} - -/** Ensure a project is valid before opening it... */ -bool -Project::validate ( const char *name ) -{ - bool r = true; - - char pwd[512]; - - fl_filename_absolute( pwd, sizeof( pwd ), "." ); - - if ( chdir( name ) ) - { - WARNING( "Cannot change to project dir \"%s\"", name ); - return false; - } - - if ( ! exists( "info" ) || - ! exists( "history" ) || - ! exists( "sources" ) ) -// ! exists( "options" ) ) - { - WARNING( "Not a Non-DAW project: \"%s\"", name ); - r = false; - } - - chdir( pwd ); - - return r; -} - -void -Project::make_engine ( void ) -{ - if ( engine ) - FATAL( "Engine should be null!" ); - - engine = new Engine; - - if ( ! engine->init( instance_name, JACK::Client::SLOW_SYNC | JACK::Client::TIMEBASE_MASTER )) - FATAL( "Could not connect to JACK!" ); - - timeline->sample_rate( engine->sample_rate() ); - - /* always start stopped (please imagine for me a realistic - * scenario requiring otherwise */ - transport->stop(); -} - - -/** Try to open project /name/. Returns 0 if sucsessful, an error code - * otherwise */ -int -Project::open ( const char *name ) -{ - if ( ! validate( name ) ) - return E_INVALID; - - close(); - - chdir( name ); - - if ( ! acquire_lock( &_lockfd, ".lock" ) ) - return E_LOCKED; - - int version; - nframes_t rate; - char *creation_date; - char *created_by; - - if ( ! read_info( &version, &rate, &creation_date, &created_by ) ) - return E_INVALID; - - if ( strncmp( created_by, "The Non-DAW", strlen( "The Non-DAW" ) ) && - strncmp( created_by, "Non-DAW", strlen( "Non-DAW" ) ) && - strncmp( created_by, APP_TITLE, strlen( APP_TITLE ) ) && - strncmp( created_by, APP_NAME, strlen( APP_NAME ) ) ) - return E_INVALID; - - if ( version > PROJECT_VERSION ) - return E_VERSION; - - if ( version < 2 ) - { - /* FIXME: Version 1->2 adds Cursor_Sequence and Cursor_Point to default project... */ - } - - /* normally, engine will be NULL after a close or on an initial open, - but 'new' will have already created it to get the sample rate. */ - if ( ! engine ) - make_engine(); - - { - Block_Timer timer( "Replayed journal" ); - if ( ! Loggable::open( "history" ) ) - return E_INVALID; - } - - /* /\* really a good idea? *\/ */ - /* timeline->sample_rate( rate ); */ - - if ( creation_date ) - { - strcpy( _created_on, creation_date ); - free( creation_date ); - } - else - *_created_on = 0; - - if ( created_by ) - free( created_by ); - - - *_path = '\0'; - - fl_filename_absolute( _path, sizeof( _path ), "." ); - - set_name( _path ); - - _is_open = true; - - tle->load_timeline_settings(); - - timeline->zoom_fit(); - - MESSAGE( "Loaded project \"%s\"", _path ); - - return 0; -} - -/** Create a new project /name/ from existing template - * /template_name/ */ -bool -Project::create ( const char *name, const char *template_name ) -{ - if ( exists( name ) ) - { - WARNING( "Project already exists" ); - return false; - } - - close(); - - if ( mkdir( name, 0777 ) ) - { - WARNING( "Cannot create project directory" ); - return false; - } - - if ( chdir( name ) ) - FATAL( "WTF? Cannot change to new project directory" ); - - mkdir( "sources", 0777 ); - creat( "history", 0666 ); - - if ( ! engine ) - make_engine(); - - /* TODO: copy template */ - - write_info(); - - if ( open( name ) == 0 ) - { - /* add the bare essentials */ - timeline->beats_per_minute( 0, 120 ); - timeline->time( 0, 4, 4 ); - - MESSAGE( "Created project \"%s\" from template \"%s\"", name, template_name ); - return true; - } - else - { - WARNING( "Failed to open newly created project" ); - return false; - } -} - -/** Replace the journal with a snapshot of the current state */ -void -Project::compact ( void ) -{ - Block_Timer timer( "Compacted journal" ); - Loggable::compact(); -} diff --git a/timeline/src/Project.H b/timeline/src/Project.H deleted file mode 100644 index a1a67a4..0000000 --- a/timeline/src/Project.H +++ /dev/null @@ -1,66 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -const char template_dir[] = "share/non-daw/templates"; -const char user_template_dir[] = "~/.non-daw/templates"; - -#include "types.h" - -class Project -{ - - static int _lockfd; - static bool _is_open; - static char _name[256]; - static char _path[512]; - static char _created_on[40]; - - static bool write_info ( void ); - static bool read_info ( int *version, nframes_t *sample_rate, char **creation_date, char **created_by ); - static const char *_errstr[]; - - static void make_engine ( void ); - -public: - - enum - { - E_INVALID = -1, - E_LOCKED = -2, - E_PERM = -3, - E_SAMPLERATE = -4, - E_VERSION = -5 - }; - - static void set_name ( const char *name ); - - static const char *errstr ( int n ) { return _errstr[ ( 0 - n ) - 1 ]; } - - static const char * path ( void ) { return Project::_path; } - static const char *name ( void ) { return Project::_name; } - static void compact ( void ); - static bool close ( void ); - static bool save ( void ); - static bool validate ( const char *name ); - static int open ( const char *name ); - static bool open ( void ) { return _is_open; } - static bool create ( const char *name, const char *template_name ); - static void undo ( void ); - static const char *created_on ( void ) { return _created_on; } -}; diff --git a/timeline/src/RWLock.H b/timeline/src/RWLock.H deleted file mode 100644 index b21d945..0000000 --- a/timeline/src/RWLock.H +++ /dev/null @@ -1,73 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include - -class RWLock -{ - - pthread_rwlock_t _lock; - -public: - - RWLock ( ) - { -// _lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - pthread_rwlock_init( &_lock, NULL ); - } - - virtual ~RWLock ( ) - { - pthread_rwlock_destroy( &_lock ); - } - - void - rdlock ( void ) - { - pthread_rwlock_rdlock( &_lock ); - } - - void - wrlock ( void ) - { - pthread_rwlock_wrlock( &_lock ); - } - - void - unlock ( void ) - { - pthread_rwlock_unlock( &_lock ); - } - - int - tryrdlock ( void ) - { - return pthread_rwlock_tryrdlock( &_lock ); - } - - int - trywrlock ( void ) - { - return pthread_rwlock_trywrlock( &_lock ); - } - -}; diff --git a/timeline/src/Sequence.C b/timeline/src/Sequence.C deleted file mode 100644 index 9fd9a07..0000000 --- a/timeline/src/Sequence.C +++ /dev/null @@ -1,621 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Sequence.H" -#include "Timeline.H" - -#include - -#include "Track.H" - -#include "FL/event_name.H" - -#include "Transport.H" // for locate() - -#include "const.h" -#include "debug.h" - -using namespace std; - - - -queue Sequence::_delete_queue; - - - -Sequence::Sequence ( Track *track, const char *name ) : Fl_Group( 0, 0, 0, 0 ), Loggable( true ) -{ - init(); - - _track = track; - - if ( name ) - _name = strdup( name ); - -// log_create(); -} - -Sequence::Sequence ( int X, int Y, int W, int H ) : Fl_Group( X, Y, W, H ), Loggable( false ) -{ - init(); -} - -void -Sequence::init ( void ) -{ - _track = NULL; - - _name = NULL; - - box( FL_FLAT_BOX ); - color( FL_BACKGROUND_COLOR ); - align( FL_ALIGN_LEFT ); - - end(); -// clear_visible_focus(); -} - - -Sequence::~Sequence ( ) -{ - DMESSAGE( "destroying sequence" ); - - if ( _widgets.size() ) - FATAL( "programming error: leaf destructor must call Sequence::clear()!" ); - - if ( parent() ) - parent()->remove( this ); - - if ( _name ) - free( _name ); -} - - - -int -Sequence::drawable_w ( void ) const -{ - return w() - Track::width(); -} - -int -Sequence::drawable_x ( void ) const -{ - return x() + Track::width(); -} - -void -Sequence::log_children ( void ) const -{ - if ( id() > 0 ) - log_create(); - - for ( std::list ::const_iterator i = _widgets.begin(); - i != _widgets.end(); ++i ) - (*i)->log_create(); -} - -/** remove all widgets from this sequence */ -void -Sequence::clear ( void ) -{ - Loggable::block_start(); - - while ( _widgets.size() ) - delete _widgets.front(); - - Loggable::block_end(); -} - -/** given screen pixel coordinate X, return an absolute frame offset into this sequence */ -nframes_t -Sequence::x_to_offset ( int X ) -{ - return timeline->xoffset + timeline->x_to_ts( X - x() ); -} - -/** sort the widgets in this sequence by position */ -void -Sequence::sort ( void ) -{ - _widgets.sort( Sequence_Widget::sort_func ); -} - -/** return a pointer to the widget that /r/ overlaps, or NULL if none. */ -Sequence_Widget * -Sequence::overlaps ( Sequence_Widget *r ) -{ - for ( list ::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) - { - if ( *i == r ) continue; - if ( (*i)->overlaps( r ) ) - return *i; - } - - return NULL; -} - -void -Sequence::handle_widget_change ( nframes_t start, nframes_t length ) -{ - /* this might be invoked from Capture or GUI thread */ -// Fl::lock(); - sort(); - timeline->damage_sequence(); -// Fl::unlock(); - -// timeline->update_length( start + length ); -} - -Sequence_Widget * -Sequence::widget_at ( nframes_t ts, int Y ) -{ - for ( list ::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); ++r ) - if ( ts >= (*r)->start() && ts <= (*r)->start() + (*r)->length() - && Y >= (*r)->y() && Y <= (*r)->y() + (*r)->h() ) - return (*r); - - return NULL; -} - -/** return a pointer to the widget under the current mouse event, or - * NULL if no widget intersects the event coordinates */ -Sequence_Widget * -Sequence::event_widget ( void ) -{ - if ( Fl::event_x() < drawable_x() ) - return NULL; - - nframes_t ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() - drawable_x() ); - return widget_at( ets, Fl::event_y() ); -} - -void -Sequence::add ( Sequence_Widget *r ) -{ -// Logger _log( this ); - - if ( r->sequence() == this ) - { - WARNING( "Programming error: attempt to add sequence widget to the same sequence twice" ); - return; - } - - if ( r->sequence() ) - { - /* This method can be called from the Capture thread as well as the GUI thread, so we must lock FLTK before redraw */ - r->redraw(); - r->sequence()->remove( r ); - } - - r->sequence( this ); - - _widgets.push_back( r ); - - handle_widget_change( r->start(), r->length() ); -} - -void -Sequence::remove ( Sequence_Widget *r ) -{ - _widgets.remove( r ); - - handle_widget_change( r->start(), r->length() ); -} - -static nframes_t -abs_diff ( nframes_t n1, nframes_t n2 ) -{ - return n1 > n2 ? n1 - n2 : n2 - n1; -} - -/** snap widget /r/ to nearest edge */ -void -Sequence::snap ( Sequence_Widget *r ) -{ - const int snap_pixels = 10; - const nframes_t snap_frames = timeline->x_to_ts( snap_pixels ); - - /* snap to other widgets */ - if ( Timeline::snap_magnetic ) - { - const int rx1 = r->start(); - const int rx2 = r->start() + r->length(); - - for ( list ::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) - { - const Sequence_Widget *w = (*i); - - if ( w == r ) - continue; - - const int wx1 = w->start(); - const int wx2 = w->start() + w->length(); - - if ( abs_diff( rx1, wx2 ) < snap_frames ) - { - r->start( w->start() + w->length() + 1 ); - - return; - } - - if ( abs_diff( rx2, wx1 ) < snap_frames ) - { - r->start( ( w->start() - r->length() ) - 1 ); - - return; - } - } - } - - nframes_t f = r->start(); - - /* snap to beat/bar lines */ - if ( timeline->nearest_line( &f ) ) - r->start( f ); -} - - -void -Sequence::draw_box ( void ) -{ - /* draw the box with the ends cut off. */ - Fl_Group::draw_box( box(), x() - Fl::box_dx( box() ) - 1, y(), w() + Fl::box_dw( box() ) + 2, h(), color() ); -} - -void -Sequence::draw ( void ) -{ - if ( damage() & ~FL_DAMAGE_USER1 ) - { - Fl_Boxtype b = box(); - box( FL_NO_BOX ); - - Fl_Group::draw(); - - box( b ); - } - - fl_push_clip( drawable_x(), y(), drawable_w(), h() ); - - draw_box(); - - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r ) - (*r)->draw_box(); - - - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r ) - (*r)->draw(); - - int X, Y, W, H; - - fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); - - timeline->draw_measure_lines( X, Y, W, H ); - - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r ) - (*r)->draw_label(); - - fl_pop_clip(); -} - -#include "FL/test_press.H" - -int -Sequence::handle ( int m ) -{ - -/* if ( m != FL_NO_EVENT ) */ -/* DMESSAGE( "%s", event_name( m ) ); */ - - switch ( m ) - { - case FL_KEYBOARD: - case FL_SHORTCUT: - if ( Fl::test_shortcut( FL_CTRL + FL_Right ) ) - { - const Sequence_Widget *w = next( transport->frame ); - - if ( w ) - transport->locate( w->start() ); - - return 1; - } - else if ( Fl::test_shortcut( FL_CTRL + FL_Left ) ) - { - const Sequence_Widget *w = prev( transport->frame ); - - if ( w ) - transport->locate( w->start() ); - - return 1; - } - else if ( Fl::test_shortcut( FL_CTRL + ' ' ) ) - { - Sequence_Widget *r = widget_at( transport->frame, y() ); - - if ( r ) - { - if ( r->selected() ) - r->deselect(); - else - r->select(); - } - } - else - { - switch ( Fl::event_key() ) - { - case FL_Left: - case FL_Right: - case FL_Up: - case FL_Down: - /* this is a hack to override FLTK's use of arrow keys for - * focus navigation */ - return timeline->handle_scroll( m ); - default: - break; - } - } - - if ( Sequence_Widget::belowmouse() ) - return Sequence_Widget::belowmouse()->dispatch( m ); - case FL_NO_EVENT: - /* garbage from overlay window */ - return 0; - case FL_FOCUS: - Fl_Group::handle( m ); - redraw(); - return 1; - case FL_UNFOCUS: - Fl_Group::handle( m ); - redraw(); - return 1; - case FL_LEAVE: -// DMESSAGE( "leave" ); - fl_cursor( FL_CURSOR_DEFAULT ); - Fl_Group::handle( m ); - return 1; - case FL_ENTER: -// DMESSAGE( "enter" ); - if ( Fl::event_x() >= drawable_x() ) - { - if ( Sequence_Widget::pushed() ) - { - if ( Sequence_Widget::pushed()->sequence()->class_name() == class_name() ) - { - /* accept objects dragged from other sequences of this type */ - if ( Sequence_Widget::pushed()->sequence() != this ) - { - timeline->sequence_lock.wrlock(); - add( Sequence_Widget::pushed() ); - timeline->sequence_lock.unlock(); - - damage( FL_DAMAGE_USER1 ); - - fl_cursor( FL_CURSOR_MOVE ); - } - } - else - fl_cursor( FL_CURSOR_DEFAULT ); - } - else - if ( ! event_widget() ) - fl_cursor( cursor() ); - - Fl_Group::handle( m ); - - return 1; - } - else - { - return Fl_Group::handle(m); - } - case FL_DND_DRAG: - case FL_DND_ENTER: - case FL_DND_LEAVE: - case FL_DND_RELEASE: - if ( Fl::event_x() >= drawable_x() ) - return 1; - else - return 0; - case FL_MOVE: - { - if ( Fl::event_x() >= drawable_x() ) - { - Sequence_Widget *r = event_widget(); - - if ( r != Sequence_Widget::belowmouse() ) - { - if ( Sequence_Widget::belowmouse() ) - Sequence_Widget::belowmouse()->handle( FL_LEAVE ); - - Sequence_Widget::belowmouse( r ); - - if ( r ) - r->handle( FL_ENTER ); - } - } - - return 1; - } - default: - { - Sequence_Widget *r = Sequence_Widget::pushed() ? Sequence_Widget::pushed() : event_widget(); - -/* if ( this == Fl::focus() ) */ -/* DMESSAGE( "Sequence widget = %p", r ); */ - - if ( m == FL_RELEASE ) - { - // in the case of track jumping, the sequence widget may not get the FL_RELEASE less we send it here: - if ( Sequence_Widget::pushed() ) - Sequence_Widget::pushed()->handle(FL_RELEASE); - - Sequence_Widget::pushed( NULL ); - } - - if ( r ) - { - int retval = r->dispatch( m ); - -/* DMESSAGE( "retval = %d", retval ); */ - - if ( m == FL_PUSH ) - take_focus(); - - if ( retval ) - { - if ( m == FL_PUSH ) - { - if ( Sequence_Widget::pushed() ) - Sequence_Widget::pushed()->handle( FL_UNFOCUS ); - - Sequence_Widget::pushed( r ); - - r->handle( FL_FOCUS ); - } - } - - if ( _delete_queue.size() ) - { - Loggable::block_start(); - - while ( _delete_queue.size() ) - { - Sequence_Widget *t = _delete_queue.front(); - _delete_queue.pop(); - - if ( Sequence_Widget::pushed() == t ) - Sequence_Widget::pushed( NULL ); - if ( Sequence_Widget::belowmouse() == t ) - { - Sequence_Widget::belowmouse()->handle( FL_LEAVE ); - Sequence_Widget::belowmouse( NULL ); - } - - timeline->sequence_lock.wrlock(); - delete t; - timeline->sequence_lock.unlock(); - } - - Loggable::block_end(); - } - - if ( m == FL_PUSH ) - return 1; - else - return retval; - } - else - { - if ( test_press( FL_BUTTON1 ) ) - { - /* traditional selection model */ - Sequence_Widget::select_none(); - } - - return Fl_Group::handle( m ); - } - } - } -} - - - -/**********/ -/* Public */ -/**********/ - -/** calculate the length of this sequence by looking at the end of the - * least widget it contains */ - -/** return the length in frames of this sequence calculated from the - * right edge of the rightmost widget */ - nframes_t - Sequence::length ( void ) const - { - nframes_t l = 0; - - for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r ) - l = max( l, (*r)->start() + (*r)->length() ); - - return l; - } - -/** return the location of the next widget from frame /from/ */ -const Sequence_Widget * - Sequence::next ( nframes_t from ) const - { - for ( list ::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) -// if ( (*i)->start() >= from ) - if ( (*i)->start() > from ) - return *i; - - if ( _widgets.size() ) - return _widgets.back(); - else - return 0; - } - -/** return the location of the next widget from frame /from/ */ -const Sequence_Widget * - Sequence::prev ( nframes_t from ) const - { - for ( list ::const_reverse_iterator i = _widgets.rbegin(); i != _widgets.rend(); i++ ) - if ( (*i)->start() < from ) - return *i; - - if ( _widgets.size() ) - return _widgets.front(); - else - return 0; - } - -/** delete all selected widgets in this sequence */ - void - Sequence::remove_selected ( void ) - { - Loggable::block_start(); - - for ( list ::iterator r = _widgets.begin(); r != _widgets.end(); ) - if ( (*r)->selected() ) - { - Sequence_Widget *t = *r; - _widgets.erase( r++ ); - delete t; - } - else - ++r; - - Loggable::block_end(); - } - -/** select all widgets intersecting with the range defined by the - * pixel coordinates X through W */ - void - Sequence::select_range ( int X, int W ) - { - nframes_t sts = x_to_offset( X ); - nframes_t ets = sts + timeline->x_to_ts( W ); - - for ( list ::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); ++r ) - if ( ! ( (*r)->start() > ets || (*r)->start() + (*r)->length() < sts ) ) - (*r)->select(); - } diff --git a/timeline/src/Sequence.H b/timeline/src/Sequence.H deleted file mode 100644 index c07b4f9..0000000 --- a/timeline/src/Sequence.H +++ /dev/null @@ -1,151 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include -#include -#include - -#include - -#include "Loggable.H" - -#include - -#include -#include - -class Track; -class Sequence_Widget; - -#include "types.h" - -/* This is the base class for all track types. */ - -class Sequence : public Fl_Group, public Loggable -{ - - /* not permitted */ - Sequence ( const Sequence &rhs ); - Sequence & operator= ( const Sequence &rhs ); - - static std::queue _delete_queue; - - void init ( void ); - -protected: - - Track *_track; /* track this sequence belongs to */ - - char *_name; - - friend class Timeline; // for draw_measure - std::list _widgets; - Sequence_Widget *widget_at ( nframes_t ts, int Y ); - Sequence_Widget *event_widget ( void ); - -public: - - virtual void log_children ( void ) const; - - /* child classes should implement this if they need to take - special action when a widget is changed/moved/resized. /start/ - and /length/ define the affected region */ - virtual void handle_widget_change ( nframes_t start, nframes_t length ); - - /* welcome to C++ */ - LOG_NAME_FUNC( Sequence ); - - Sequence ( Track *track=0, const char *name = 0 ); - - Sequence ( int X, int Y, int W, int H ); - - virtual ~Sequence ( ); - - /* override this to provide cursor */ - virtual Fl_Cursor cursor ( void ) const = 0; - - nframes_t x_to_offset ( int X ); - - const char * name ( void ) const { return _name; } - void name ( const char *s ) - { - if ( _name ) free( _name ); - _name = s ? strdup( s ) : NULL; - label( _name ); - - /* for outside label */ - if ( (Fl_Widget*)track() ) - ((Fl_Widget*)track())->redraw(); - } - - void sort ( void ); - void clear ( void ); - - int drawable_x ( void ) const; - int drawable_w ( void ) const; - - const Sequence_Widget *next ( nframes_t from ) const; - const Sequence_Widget *prev ( nframes_t from ) const; - - Track *track ( void ) const { return _track; } - void track ( Track *t ) { _track = t; } - - void remove ( Sequence_Widget *r ); - void add ( Sequence_Widget *r ); - - void select_range ( int X, int W ); - - void remove_selected ( void ); - - Fl_Color color ( void ) const { return this == Fl::focus() ? fl_color_average( FL_FOREGROUND_COLOR, Fl_Widget::color(), 0.20f ) : Fl_Widget::color(); } - void color ( Fl_Color v ) { Fl_Widget::color( v ); } - - const std::list widgets ( void ) const { return _widgets; } - - void queue_delete ( Sequence_Widget *r ) - { - _delete_queue.push( r ); - } - - Sequence_Widget * overlaps ( Sequence_Widget *r ); - - nframes_t length ( void ) const; - - virtual Sequence * clone ( void ) - { - assert( 0 ); - return NULL; - } - - virtual Sequence * clone_empty ( void ) - { - return NULL; - } - - virtual void snap ( Sequence_Widget *r ); - virtual int handle ( int m ); - virtual void draw ( void ); - virtual void draw_box ( void ); - - virtual nframes_t process ( nframes_t ) { return 0; } - -}; diff --git a/timeline/src/Sequence_Point.C b/timeline/src/Sequence_Point.C deleted file mode 100644 index afb8377..0000000 --- a/timeline/src/Sequence_Point.C +++ /dev/null @@ -1,122 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Sequence_Point.H" - -#include - - - -Sequence_Point::Sequence_Point ( const Sequence_Point &rhs ) : Sequence_Widget( rhs ) -{ -} - -Sequence_Point::Sequence_Point ( ) -{ - color( FL_CYAN ); -} - -Sequence_Point::~Sequence_Point ( ) -{ -} - - - -void -Sequence_Point::get ( Log_Entry &e ) const -{ - Sequence_Widget::get( e ); -} - -void -Sequence_Point::set ( Log_Entry &e ) -{ - Sequence_Widget::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( ":start", s ) ) - { - sequence()->sort(); - } - - } -} - -static void -draw_marker ( Fl_Color c ) -{ - fl_color( c ); - - fl_begin_polygon(); - -#define vv(x,y) fl_vertex( x, y ); - - vv( 0.0, 0.0 ); - vv( 0.0, 0.6 ); - vv( 0.5, 1.0 ); - vv( 1.0, 0.6 ); - vv( 1.0, 0.0 ); - vv( 0.0, 0.0 ); - - fl_end_polygon(); - - fl_color( fl_darker( c ) ); - - fl_begin_line(); - - vv( 0.0, 0.0 ); - vv( 0.0, 0.6 ); - vv( 0.5, 1.0 ); - vv( 1.0, 0.6 ); - vv( 1.0, 0.0 ); - vv( 0.0, 0.0 ); - - fl_end_line(); -} - -void -Sequence_Point::draw_box ( void ) -{ - const int X = x() - (abs_w() >> 1); - - const int Y = y(); - - fl_push_matrix(); - fl_translate( X, Y ); - fl_scale( abs_w(), h() ); - - Fl_Color c = selected() ? selection_color() : color(); - - draw_marker( c ); - - fl_pop_matrix(); -} - -void -Sequence_Point::draw ( void ) -{ -// Sequence_Widget::draw(); - - draw_label( _label, align() ); -} diff --git a/timeline/src/Sequence_Point.H b/timeline/src/Sequence_Point.H deleted file mode 100644 index af64b46..0000000 --- a/timeline/src/Sequence_Point.H +++ /dev/null @@ -1,56 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence_Widget.H" - -class Sequence_Point : public Sequence_Widget -{ - /* not permitted */ - Sequence_Point & operator= ( const Sequence_Point &rhs ); - -protected: - - void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - virtual void draw_box ( void ); - virtual void draw ( void ); - - Sequence_Point ( const Sequence_Point &rhs ); - Sequence_Point ( ); - virtual ~Sequence_Point ( ); - -public: - - Fl_Align align ( void ) const { return FL_ALIGN_RIGHT; } - virtual long abs_w ( void ) const { return 8; } - -// virtual int abs_x ( void ) const { return Sequence_Widget::abs_x() - ( abs_w() >> 1 ); } -// virtual int x ( void ) const { return Sequence_Widget::line_x() - ( abs_w() >> 1 ); } - - virtual int x ( void ) const - { - return line_x(); - } - - nframes_t length ( void ) const { return timeline->x_to_ts( abs_w() ); } - -}; diff --git a/timeline/src/Sequence_Region.C b/timeline/src/Sequence_Region.C deleted file mode 100644 index c119467..0000000 --- a/timeline/src/Sequence_Region.C +++ /dev/null @@ -1,258 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Sequence_Region.H" -#include "Track.H" - -#include - - - -Sequence_Region::Sequence_Region ( ) -{ - color( FL_CYAN ); -} - -Sequence_Region::Sequence_Region ( const Sequence_Region &rhs ) : Sequence_Widget( rhs ) -{ -} - -Sequence_Region::~Sequence_Region ( ) -{ -} - - - -void -Sequence_Region::get ( Log_Entry &e ) const -{ - e.add( ":color", _box_color ); - e.add( ":length", _r->length ); - - Sequence_Widget::get( e ); -} - -void -Sequence_Region::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":color" ) ) - _box_color = (Fl_Color)atoll( v ); - else if ( ! strcmp( s, ":length" ) ) - _r->length = atoll( v ); - - } - - Sequence_Widget::set( e ); -} - -void -Sequence_Region::trim_left ( nframes_t where ) -{ - nframes_t f = where; - - /* snap to beat/bar lines */ - if ( timeline->nearest_line( &f ) ) - where = f; - - if ( where > _r->start + _r->length ) - where = _r->start + _r->length; - - if ( where < _r->start && _r->offset < _r->start - where ) - where = _r->start - _r->offset; - - _r->set_left( where ); -} - -void -Sequence_Region::trim_right ( nframes_t where ) -{ - nframes_t f = where; - - /* snap to beat/bar lines */ - if ( timeline->nearest_line( &f ) ) - where = f; - - if ( where < _r->start ) - where = _r->start; - - _r->set_right( where ); -} - -void -Sequence_Region::trim ( enum trim_e t, int X ) -{ - redraw(); - - nframes_t where = timeline->x_to_offset( X ); - - switch ( t ) - { - case LEFT: - trim_left( where ); - break; - case RIGHT: - trim_right( where ); - break; - default: - break; - } -} - -/** split region at absolute frame /where/. due to inheritance issues, - * the copy must be made in the derived classed and passed in */ -void -Sequence_Region::split ( Sequence_Region * copy, nframes_t where ) -{ - trim_right( where ); - copy->trim_left( where ); - sequence()->add( copy ); -} - - -#include "FL/test_press.H" - -int -Sequence_Region::handle ( int m ) -{ - static enum trim_e trimming; - - int X = Fl::event_x(); - int Y = Fl::event_y(); - - Logger _log( this ); - - switch ( m ) - { - case FL_PUSH: - { - /* trimming */ - if ( Fl::event_shift() && ! Fl::event_ctrl() ) - { - switch ( Fl::event_button() ) - { - case 1: - trim( trimming = LEFT, X ); - begin_drag( Drag( X, Y ) ); - _log.hold(); - break; - case 3: - trim( trimming = RIGHT, X ); - begin_drag( Drag( X, Y) ); - _log.hold(); - break; - default: - return 0; - break; - } - - fl_cursor( FL_CURSOR_WE ); - return 1; - } - else if ( test_press( FL_BUTTON2 ) ) - { - if ( Sequence_Widget::current() == this ) - { - if ( selected() ) - deselect(); - else - select(); - } - - redraw(); - return 1; - } - -/* else if ( test_press( FL_CTRL + FL_BUTTON1 ) ) */ -/* { */ -/* /\* duplication *\/ */ -/* fl_cursor( FL_CURSOR_MOVE ); */ -/* return 1; */ -/* } */ - - else - return Sequence_Widget::handle( m ); - } - case FL_RELEASE: - { - Sequence_Widget::handle( m ); - - if ( trimming != NO ) - trimming = NO; - - return 1; - } - case FL_DRAG: - { - if ( ! _drag ) - { - begin_drag( Drag( X, Y, x_to_offset( X ) ) ); - _log.hold(); - } - - /* trimming */ - if ( Fl::event_shift() ) - { - if ( trimming ) - { - trim( trimming, X ); - return 1; - } - else - return 0; - } - - return Sequence_Widget::handle( m ); - } - default: - return Sequence_Widget::handle( m ); - break; - } - - return 0; - -} - -void -Sequence_Region::draw_box ( void ) -{ - Fl_Color c = selected() ? selection_color() : box_color(); - - fl_draw_box( box(), x(), y(), w(), h(), fl_color_add_alpha( c, 127 ) ); -} - -void -Sequence_Region::draw ( void ) -{ - -} - -void -Sequence_Region::draw_label ( const char *label, Fl_Align align, Fl_Color color, int xo, int yo ) -{ - fl_color( active_r() ? FL_FOREGROUND_COLOR : fl_inactive( FL_FOREGROUND_COLOR ) ); - fl_font( FL_HELVETICA_ITALIC, 10 ); - fl_draw( label, line_x() + Fl::box_dx( box() ), y() + Fl::box_dy( box() ), abs_w() - Fl::box_dw( box() ), h() - Fl::box_dh( box() ), align ); -} - diff --git a/timeline/src/Sequence_Region.H b/timeline/src/Sequence_Region.H deleted file mode 100644 index 8be8b81..0000000 --- a/timeline/src/Sequence_Region.H +++ /dev/null @@ -1,58 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence.H" -#include "Sequence_Widget.H" - -/* Base class representing a /region/ of time on a /sequence/, with - controls for the offset and length points. */ - -class Sequence_Region : public Sequence_Widget -{ - -protected: - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - Sequence_Region ( ); - Sequence_Region ( const Sequence_Region &rhs ); - virtual ~Sequence_Region ( ); - - virtual Fl_Align align ( void ) const { return FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_WRAP; } - virtual int handle ( int m ); - virtual void draw_box( void ); - virtual void draw ( void ); - virtual void draw_label ( void ) { Sequence_Widget::draw_label(); } - virtual void draw_label ( const char *label, Fl_Align align, Fl_Color color=(Fl_Color)0, int xo=0, int yo=0 ); - -public: - - LOG_NAME_FUNC( Region ); - - void trim_right ( nframes_t where ); - void trim_left ( nframes_t where ); - - enum trim_e { NO, LEFT, RIGHT }; - void trim ( enum trim_e t, int X ); - - void split ( Sequence_Region *copy, nframes_t where ); -}; diff --git a/timeline/src/Sequence_Widget.C b/timeline/src/Sequence_Widget.C deleted file mode 100644 index ea9a858..0000000 --- a/timeline/src/Sequence_Widget.C +++ /dev/null @@ -1,596 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - -#include "Sequence_Widget.H" -#include "Track.H" - -#include "const.h" -#include "debug.h" - -using namespace std; - - - -list Sequence_Widget::_selection; -Sequence_Widget * Sequence_Widget::_current = NULL; -Sequence_Widget * Sequence_Widget::_pushed = NULL; -Sequence_Widget * Sequence_Widget::_belowmouse = NULL; -Fl_Color Sequence_Widget::_selection_color = FL_MAGENTA; - - - -Sequence_Widget::Sequence_Widget ( ) -{ - _label = 0; - _sequence = NULL; - - _r = &_range; - - _r->start = _r->offset = _r->length = 0; - - _drag = NULL; - - _box_color = FL_BACKGROUND_COLOR; - _color = FL_FOREGROUND_COLOR; -} - -/* careful with this, it doesn't journal */ -Sequence_Widget::Sequence_Widget ( const Sequence_Widget &rhs ) : Loggable( rhs ) -{ - _drag = NULL; - - if ( rhs._label ) - _label = strdup( rhs._label ); - else - _label = 0; - - - _range = rhs._range; - _dragging_range = rhs._dragging_range; - _r = &_range; - - _color = rhs._color; - _box_color = rhs._box_color; - - _sequence = NULL; - - if ( rhs._sequence ) - rhs._sequence->add( this ); -}; - -const Sequence_Widget & -Sequence_Widget::operator= ( const Sequence_Widget &rhs ) -{ - if ( this == &rhs ) - return *this; - - _r = &_range; - _range = rhs._range; - _dragging_range = rhs._dragging_range; - _sequence = rhs._sequence; - _box_color = rhs._box_color; - _color = rhs._color; - - if ( rhs._label ) - _label = strdup( rhs._label ); - - return *this; -} - -Sequence_Widget::~Sequence_Widget ( ) -{ - redraw(); - - if ( this == _pushed ) - _pushed = NULL; - - if ( this == _belowmouse ) - _belowmouse = NULL; - - label( NULL ); - - _sequence->remove( this ); - - _selection.remove( this ); -} - - - -void -Sequence_Widget::get ( Log_Entry &e ) const -{ - e.add( ":start", _r->start ); -// e.add( ":offset", _r->offset ); -// e.add( ":length", _r->length ); - e.add( ":sequence", _sequence ); - e.add( ":selected", selected() ); -} - -void -Sequence_Widget::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":start" ) ) - _r->start = atoll( v ); -// else if ( ! strcmp( s, ":offset" ) ) -// _r->offset = atoll( v ); -// else if ( ! strcmp( s, ":length" ) ) -// _r->length = atoll( v ); - else if ( ! strcmp( s, ":selected" ) ) - { - if ( atoi( v ) ) - select(); - else - deselect(); - } - else if ( ! strcmp( s, ":sequence" ) ) - { - int i; - sscanf( v, "%X", &i ); - Sequence *t = (Sequence*)Loggable::find( i ); - - ASSERT( t, "No such object ID (%s)", v ); - - t->add( this ); - } -// else -// e.erase( i ); - } - - if ( _sequence ) - { - _sequence->handle_widget_change( _r->start, _r->length ); - _sequence->damage( FL_DAMAGE_USER1 ); - } -} - -void -Sequence_Widget::begin_drag ( const Drag &d ) -{ - _drag = new Drag( d ); - - timeline->sequence_lock.wrlock(); - - /* copy current values */ - - _dragging_range = _range; - - /* tell display to use temporary */ - _r = &_dragging_range; - - timeline->sequence_lock.unlock(); -} - -void -Sequence_Widget::end_drag ( void ) -{ - /* swap in the new value */ - /* go back to playback and display using same values */ - - timeline->sequence_lock.wrlock(); - - _range = _dragging_range; - _r = &_range; - - delete _drag; - _drag = NULL; - - /* this will result in a sort */ - sequence()->handle_widget_change( _r->start, _r->length ); - - timeline->sequence_lock.unlock(); -} - -/** set position of widget on the timeline. */ -void -Sequence_Widget::start ( nframes_t where ) -{ - /* this is pretty complicated because of selection and snapping */ - - if ( ! selected() ) - { - redraw(); - _r->start = where; - } - else - { - if ( this != Sequence_Widget::_current ) - return; - - /* difference between where we are current and desired position */ - - if ( where < _r->start ) - { - nframes_t d = _r->start - where; - - /* first, make sure we stop at 0 */ - nframes_t m = JACK_MAX_FRAMES; - - /* find the earliest region start point */ - for ( list ::const_iterator i = _selection.begin(); i != _selection.end(); ++i ) - m = min( m, (*i)->_r->start ); - - if ( d > m ) - d = 0; - - for ( list ::iterator i = _selection.begin(); i != _selection.end(); ++i ) - { - (*i)->redraw(); - (*i)->_r->start -= d; - } - } - else - { - nframes_t d = where - _r->start; - - /* TODO: do like the above and disallow wrapping */ - for ( list ::iterator i = _selection.begin(); i != _selection.end(); ++i ) - { - (*i)->redraw(); - (*i)->_r->start += d; - } - } - } -} - -void -Sequence_Widget::draw_label ( void ) -{ -} - -void -Sequence_Widget::draw_label ( const char *label, Fl_Align align, Fl_Color color, int xo, int yo ) -{ - int X = x(); - int Y = y(); - int W = w(); - int H = h(); - - if ( align & FL_ALIGN_CLIP ) fl_push_clip( X, Y, W, H ); - - X += xo; - Y += yo; - - Fl_Label lab; - - lab.color = color; -// lab.type = FL_SHADOW_LABEL; - lab.type = FL_NORMAL_LABEL; - lab.value = label; - lab.font = FL_HELVETICA_ITALIC; - lab.size = 9; - - int lw = 0, lh = 0; - - fl_font( lab.font, lab.size ); - fl_measure( lab.value, lw, lh ); - - int dx = 0; - - /* adjust for scrolling */ - if ( abs_x() < scroll_x() ) - dx = min( 32767, scroll_x() - abs_x() ); - - const Fl_Boxtype b = FL_BORDER_BOX; - const int bx = Fl::box_dx( b ); - const int bw = Fl::box_dw( b ); - const int by = Fl::box_dy( b ); - const int bh = Fl::box_dh( b ); - - /* FIXME: why do we have to do this here? why doesn't Fl_Label::draw take care of this stuff? */ - if ( align & FL_ALIGN_INSIDE ) - { - if ( align & FL_ALIGN_BOTTOM ) - Y += h() - ( lh + bh ); - else if ( align & FL_ALIGN_TOP ) - Y += by; - else - Y += ( h() / 2 ) - ( lh + bh ); - - if ( align & FL_ALIGN_RIGHT ) - X += abs_w() - ( lw + bw ); - else if ( align & FL_ALIGN_LEFT ) - X += bx; - else - X += ( abs_w() / 2 ) - ( ( lw + bw ) / 2 ); - - } - else - { - if ( align & FL_ALIGN_RIGHT ) - X += abs_w(); - else if ( align & FL_ALIGN_LEFT ) - X -= lw + bw; - else - X += ( abs_w() / 2 ) - ( ( lw + bw ) / 2 ); - - if ( align & FL_ALIGN_BOTTOM ) - Y += h(); - else if ( align & FL_ALIGN_TOP ) - Y -= lh + bh; - else - Y += ( h() / 2 ) - ( ( lh + bh ) / 2 ); - } - - fl_draw_box( b, ( X - dx ), Y - by, lw + bw, lh + bh, fl_color_add_alpha( FL_DARK1, 150 ) ); - - fl_color( color ); - - fl_draw( label, ( X - dx ), Y, lw + bw, lh, (Fl_Align)(FL_ALIGN_CENTER) ); - - if ( align & FL_ALIGN_CLIP ) fl_pop_clip(); -} - -int -Sequence_Widget::dispatch ( int m ) -{ - Sequence_Widget::_current = this; - - if ( selected() ) - { - Loggable::block_start(); - - int r = 0; - - for ( list ::iterator i = _selection.begin(); i != _selection.end(); i++ ) - if ( *i != this ) - r |= (*i)->handle( m ); - - r |= handle( m ); - - Loggable::block_end(); - - return r; - } - else - return handle( m ); -} - -void -Sequence_Widget::draw ( void ) -{ - draw_box(); -} - -void -Sequence_Widget::draw_box ( void ) -{ - fl_draw_box( box(), x(), y(), w(), h(), selected() ? FL_MAGENTA : _box_color ); -} - - -#include "FL/test_press.H" - -/* base hanlde just does basic dragging */ -int -Sequence_Widget::handle ( int m ) -{ - int X = Fl::event_x(); - int Y = Fl::event_y(); - - Logger _log( this ); - - switch ( m ) - { - case FL_ENTER: - fl_cursor( FL_CURSOR_HAND ); - return 1; - case FL_LEAVE: -// DMESSAGE( "leave" ); - fl_cursor( sequence()->cursor() ); - return 1; - case FL_PUSH: - { - /* deletion */ - if ( test_press( FL_BUTTON3 + FL_CTRL ) ) - { - remove(); - - return 1; - } - else if ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) ) - { - /* traditional selection model */ - if ( Fl::event_ctrl() ) - select(); - - fl_cursor( FL_CURSOR_MOVE ); - - /* movement drag */ - return 1; - } - - return 0; - } - case FL_RELEASE: - - if ( _drag ) - { - end_drag(); - _log.release(); - } - - fl_cursor( FL_CURSOR_HAND ); - - return 1; - case FL_DRAG: - { - Fl::event_key( 0 ); - - if ( ! _drag ) - { - begin_drag ( Drag( X, Y, x_to_offset( X ), start() ) ); - _log.hold(); - } - - if ( test_press( FL_BUTTON1 + FL_CTRL ) && ! _drag->state ) - { - /* duplication */ - timeline->sequence_lock.wrlock(); - sequence()->add( this->clone() ); - timeline->sequence_lock.unlock(); - - _drag->state = 1; - return 1; - } - else if ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) ) - { - redraw(); - - const nframes_t of = timeline->x_to_offset( X ); - - int64_t s = (int64_t)of - _drag->offset; - - if ( s < 0 ) - s = 0; - - start(s); - - if ( Sequence_Widget::_current == this ) - sequence()->snap( this ); - - if ( X >= sequence()->x() + sequence()->w() || - X <= sequence()->drawable_x() ) - { - /* this drag needs to scroll */ - - int64_t pos = s - ( _drag->mouse_offset - _drag->offset ); - - - if ( X > sequence()->x() + sequence()->w() ) - pos -= timeline->x_to_ts( sequence()->drawable_w() ); - - if ( s == 0 ) - pos = 0; - - if ( pos < 0 ) - pos = 0; - - timeline->xposition(timeline->ts_to_x(pos)); - - /* timeline->redraw(); */ - sequence()->damage( FL_DAMAGE_USER1 ); - } - - if ( ! selected() || _selection.size() == 1 ) - { - /* track jumping */ - if ( Y > _sequence->y() + _sequence->h() || Y < _sequence->y() ) - { - Track *t = timeline->track_under( Y ); - - fl_cursor( FL_CURSOR_HAND ); - - if ( t ) - t->handle( FL_ENTER ); - - return 0; - } - } - - return 1; - } - else - { - DMESSAGE( "unknown" ); - return 0; - } - } - default: - return 0; - } -} - - -/**********/ -/* Public */ -/**********/ - -/** add this widget to the selection */ -void -Sequence_Widget::select ( void ) -{ - if ( selected() ) - return; - - _selection.push_back( this ); - _selection.sort( sort_func ); - - redraw(); -} - -/** remove this widget from the selection */ -void -Sequence_Widget::deselect ( void ) -{ - _selection.remove( this ); - redraw(); -} - -bool -Sequence_Widget::selected ( void ) const -{ - return std::find( _selection.begin(), _selection.end(), this ) != _selection.end(); -} - -/** remove this widget from its sequence */ -void -Sequence_Widget::remove ( void ) -{ - redraw(); - sequence()->queue_delete( this ); -} - -void -Sequence_Widget::delete_selected ( void ) -{ - Loggable::block_start(); - - while ( _selection.size() ) - delete _selection.front(); - - Loggable::block_end(); -} - -void -Sequence_Widget::select_none ( void ) -{ - Loggable::block_start(); - - while ( _selection.size() ) - { - Sequence_Widget *w = _selection.front(); - - w->log_start(); - - _selection.front()->redraw(); - _selection.pop_front(); - - w->log_end(); - } - - Loggable::block_end(); -} diff --git a/timeline/src/Sequence_Widget.H b/timeline/src/Sequence_Widget.H deleted file mode 100644 index 210f72b..0000000 --- a/timeline/src/Sequence_Widget.H +++ /dev/null @@ -1,342 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence.H" -#include "Loggable.H" -#include "Timeline.H" -#include -#include -using std::min; -using std::max; - -class Sequence_Widget; - -struct Drag -{ - /* mouse coords at offset of drag */ - int x; - int y; - int state; - -// nframes_t start; - int64_t offset; - int64_t mouse_offset; - - Drag( int X, int Y, uint64_t offset=0, uint64_t mouse_offset = 0 ) : x( X ), y( Y ), offset( offset ), mouse_offset( mouse_offset ) { state = 0; } -}; - -/* most common position description. /offset/ is only used by Regions, - but it's more convenient to have it here */ -struct Range -{ - nframes_t start; /* where on the timeline */ - nframes_t offset; /* first sample from clip */ - nframes_t length; /* total number of samples */ - - void - set_left ( nframes_t f ) - { - offset += f - start; - length -= f - start; - start = f; - } - - void - set_right ( nframes_t f ) - { - length = f - start; - } - - Range ( ) : start( 0 ), offset( 0 ), length( 0 ) - { - } -}; - -/* Used by time/tempo points or any other child of Sequence_Widget - which must be locked to a point in musical time rather than wallclock - time. Bar and beat start at 1. */ -struct BBT -{ - unsigned short bar; - unsigned char beat; - unsigned short tick; - - BBT ( ) : bar( 0 ), beat( 0 ), tick( 0 ) - { - } -}; - - -/* FIXME: wrong place for this */ -struct position_info -{ - nframes_t frame; - - float tempo; - int beats_per_bar; - int beat_type; - - BBT bbt; -}; - -#define SEQUENCE_WIDGET_CLONE_FUNC(class) \ - virtual Sequence_Widget *clone ( void ) const \ - { \ - return new class ( *this ); \ - } - - -/* Base class for virtual widget on a track */ -class Sequence_Widget : public Loggable -{ - - static std::list _selection; /* all the widgets making up the selection */ - - /* FIXME: is this not the same as /pushed/? */ - static Sequence_Widget * _current; /* the widget initiating events that affect the selection */ - - /* these are actually managed in the Sequence classes */ - static Sequence_Widget * _pushed; /* the widget receiving drag events (a copy) */ - static Sequence_Widget * _original; /* the original of the /pushed/ widget */ - static Sequence_Widget * _belowmouse; /* the widget below the mouse cursor */ - - - static Fl_Color _selection_color; - - -protected: - - char *_label; - - Sequence *_sequence; /* track this region belongs to */ - - Range _range; /* always used by RT/osc threads */ - Range _dragging_range; /* used when dragging */ - - Range *_r; /* range for editing / display (points to the same thing as above, except for when dragging etc) */ - - Fl_Color _color; /* color of waveform */ - Fl_Color _box_color; /* color of background (box) */ - - Drag *_drag; - - virtual void get ( Log_Entry &e ) const; - virtual void set ( Log_Entry &e ); - - Sequence_Widget ( const Sequence_Widget &rhs ); - Sequence_Widget ( ); - - const Sequence_Widget & - operator= ( const Sequence_Widget &rhs ); - -public: - - - virtual ~Sequence_Widget ( ); - - virtual Sequence_Widget *clone ( void ) const = 0; - - bool selected ( void ) const; - static int nselected ( void ) - { return _selection.size(); } - void select ( void ); - void deselect ( void ); - void remove ( void ); - - static void delete_selected ( void ); - static void select_none ( void ); - - static Sequence_Widget *current ( void ) { return Sequence_Widget::_current; } - static Sequence_Widget *pushed ( void ) { return Sequence_Widget::_pushed; } - static Sequence_Widget *belowmouse ( void ) { return Sequence_Widget::_belowmouse; } - - static void pushed ( Sequence_Widget *w ) { Sequence_Widget::_pushed = w; } - static void belowmouse ( Sequence_Widget *w ) { Sequence_Widget::_belowmouse = w; } - - void begin_drag ( const Drag &d ); - void end_drag ( void ); - - int dispatch ( int m ); - - Fl_Widget * parent ( void ) const { return _sequence; } - - int scroll_x ( void ) const { return timeline->ts_to_x( timeline->xoffset ); } - nframes_t scroll_ts ( void ) const { return timeline->xoffset; } - - virtual int y ( void ) const { return _sequence->y(); } - virtual int h ( void ) const { return _sequence->h(); } - - /* used by regions */ - - int get_x( nframes_t frame ) const - { - return frame < timeline->xoffset ? - _sequence->drawable_x() - 10 : - min( _sequence->drawable_x() + _sequence->drawable_w(), - _sequence->drawable_x() + timeline->ts_to_x( frame - timeline->xoffset ) ); - } - - virtual int x ( void ) const - { - return get_x( _r->start ); - } - - /* use this as x() when you need to draw lines between widgets. Clamped to -32767-32767 to match max canvas size of FLTK/NTK */ - int line_x ( void ) const - { - return _r->start < timeline->xoffset ? - max( -32767, _sequence->drawable_x() - timeline->ts_to_x( timeline->xoffset - _r->start )) : - min( 32767, _sequence->drawable_x() + timeline->ts_to_x( _r->start - timeline->xoffset )); - } - - /* same as above but un-clamped for cairo */ - long curve_x ( void ) const - { - return _r->start < timeline->xoffset ? - _sequence->drawable_x() - timeline->ts_to_x( timeline->xoffset - _r->start ) : - _sequence->drawable_x() + timeline->ts_to_x( _r->start - timeline->xoffset ); - } - - virtual int w ( void ) const - { -// int tx = timeline->ts_to_x( _r->start ); - - long rw; - - if ( _r->start < timeline->xoffset ) - { - if ( _r->start + _r->length < timeline->xoffset ) - rw = 0; - else - rw = timeline->ts_to_x( ( _r->start + _r->length ) - timeline->xoffset ) + 10; - } - else - rw = abs_w(); - - return (int)min( rw, (long)(_sequence->drawable_w()) + 20 ); - } - - int abs_x ( void ) const { return timeline->ts_to_x( _r->start ); } - virtual long abs_w ( void ) const { return timeline->ts_to_x( _r->length ); } - - Fl_Color color ( void ) const { return _color; } - void color ( Fl_Color v ) { _color = v; } - virtual Fl_Color box_color ( void ) const { return _box_color; } - virtual void box_color ( Fl_Color v ) { _box_color = v; } - virtual Fl_Color selection_color ( void ) const { return _selection_color; } - virtual void selection_color ( Fl_Color v ) { _selection_color = v; } - virtual Fl_Color actual_box_color ( void ) const { return box_color(); } - - Sequence * sequence ( void ) const { return _sequence; } - void sequence ( Sequence *t ) { _sequence = t; } - - nframes_t start ( void ) const { return _r->start; } - -/* void start ( nframes_t o ) { _r->start = o; } */ - - void start ( nframes_t where ); - void length ( nframes_t v ) { _r->length = v; } - virtual nframes_t length ( void ) const { return _r->length; } - void offset ( nframes_t v ) { _r->offset = v; } - nframes_t offset ( void ) const { return _r->offset; } - - void set_left ( nframes_t v ) { _r->set_left( v ); } - void set_right ( nframes_t v ) { _r->set_right( v ); } - - const char *label ( void ) const { return _label; } - void label ( const char *s ) - { - if ( _label ) - free( _label ); - - _label = NULL; - - if ( s ) - _label = strdup( s ); - - redraw(); - } - - /** convert a screen x coord into an start into the region */ - nframes_t x_to_offset ( int X ) - { - return timeline->x_to_ts( scroll_x() + ( X - _sequence->drawable_x() ) ) - _r->start; - } - - int active_r ( void ) const { return _sequence->active_r(); } - -/** returns true if widget /w/ begins and ends completely within the range of this widget */ - bool contains ( const Sequence_Widget *w ) const - { - return w->start() >= start() && w->start() + w->length() <= start() + length(); - } - -/** returns true of widget /w/ overlaps this widget in any place */ - bool overlaps ( const Sequence_Widget *w ) const - { - return ! ( w->start() > start() + length() || w->start() + w->length() < start() ); - } - - virtual Fl_Boxtype box ( void ) const { return FL_UP_BOX; } - virtual Fl_Align align ( void ) const { return (Fl_Align)0; } - - virtual void - redraw ( void ) - { - if ( ! _sequence ) - return; - - if ( ! (align() & FL_ALIGN_INSIDE) ) - { - // FIXME: do better.. - _sequence->damage( FL_DAMAGE_USER1 ); - } - else - _sequence->damage( FL_DAMAGE_USER1, x(), y(), w(), h() ); - } - - virtual void draw_box ( void ); - virtual void draw ( void ); - virtual void draw_label ( void ); - virtual void draw_label ( const char *label, Fl_Align align, Fl_Color color=(Fl_Color)0, int xo=0, int yo=0 ); - - bool - operator< ( const Sequence_Widget & rhs ) const - { - return _r->start < rhs._r->start; - } - - bool - operator<=( const Sequence_Widget & rhs ) const - { - return _r->start <= rhs._r->start; - } - - virtual int handle ( int m ); - - static bool - sort_func ( const Sequence_Widget *lhs, const Sequence_Widget *rhs ) - { - return *lhs < *rhs; - } - -}; diff --git a/timeline/src/TLE.fl b/timeline/src/TLE.fl deleted file mode 100644 index e54de7f..0000000 --- a/timeline/src/TLE.fl +++ /dev/null @@ -1,1132 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.H} -code_name {.C} -comment {// -// Copyright (C) 2008-2010 Jonathan Moore Liles -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -} {in_source in_header -} - -decl {const float STATUS_UPDATE_FREQ = 0.5f;} {private local -} - -decl {class Fl_Flowpack;} {public global -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include "Timeline.H"} {private local -} - -decl {\#include "Transport.H"} {private local -} - -decl {\#include "Loggable.H"} {private local -} - -decl {\#include "Project.H"} {private local -} - -decl {\#include "Clock.H"} {public local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include "Track.H" // for capture_format} {private local -} - -decl {\#include "Waveform.H" // for options} {private local -} - -decl {\#include "Audio_Region.H" // for options} {private local -} - -decl {\#include "Control_Sequence.H" // for options} {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include "Engine/Engine.H"} {private local -} - -decl {\#include "Engine/Audio_File.H" // for supported formats} {private local -} - -decl {\#include } {private local -} - -decl {extern char project_display_name[256];} {private global -} - -decl {\#include } {private local -} - -decl {extern nsm_client_t *nsm;} {private global -} - -decl {extern char *user_config_dir;} {private global -} - -decl {extern char *APP_NAME;} {private global -} - -class TLE_Window {open : {public Fl_Overlay_Window} -} { - Function {TLE_Window(int W, int H, const char *L = 0) : Fl_Overlay_Window( W, H, L )} {open - } { - code {} {} - } - Function {draw_overlay(void)} {open return_type void - } { - code {timeline->draw_overlay();} {} - } - Function {~TLE_Window()} {open return_type virtual - } { - code {} {} - } -} - -class TLE {open -} { - decl {Fl_Color system_colors[3];} {private local - } - Function {save_options()} {open - } { - code {const char options_filename[] = "options"; - // const char state_filename[] = "state"; - - // save options - - char *path; - asprintf( &path, "%s/%s", user_config_dir, options_filename ); - ((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Options" ), path ); - free( path );} {} - } - Function {save()} {open - } { - code {timeline->command_save();} {} - } - Function {quit()} {} { - code {timeline->command_quit();} {} - } - Function {open( const char *name )} {} { - code {timeline->command_load( name, NULL );} {} - } - Function {save_timeline_settings()} {open - } { - code {if ( ! Project::open() ) - return; - - -// save project local options (Timeline menu) -((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Project/Se&ttings" ), "options" );} {} - } - Function {reset_timeline_settings( void )} {open private return_type void - } { - code {char path[256]; -snprintf( path, sizeof( path ), "%s/%s", user_config_dir, ".default_project_settings" ); - -((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Project/Se&ttings" ), path );} {} - } - Function {load_timeline_settings()} {open - } { - code {reset_timeline_settings(); - - -if ( Project::open() ) - ((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Project/Se&ttings" ), "options" ); - -update_menu(); - -project_name->redraw();} {} - } - Function {run()} {} { - code {update_menu(); - -// main_window->show(); - -Fl::lock(); - -// Fl::run();} {} - } - Function {TLE()} {open - } { - code {make_window(); - -Fl::visible_focus( 0 ); - -// constrain window to size of screen. -{ - int sx, sy, sw, sh; - - Fl::screen_xywh( sx, sy, sw, sh ); - - main_window->size_range( 947, 500 ); - main_window->size( 947, 600 ); - - if ( main_window->w() > sw || - main_window->h() > sh ) - main_window->resize( sx, sy, sw, sh ); -} - -Fl::add_timeout( STATUS_UPDATE_FREQ, update_cb, this ); - -fl_message_icon()->box( FL_RSHADOW_BOX ); -fl_message_icon()->labelcolor( FL_BLACK ); -fl_message_icon()->color( FL_RED ); -fl_message_font( FL_HELVETICA, 18 ); - - -std::list formats; - -Audio_File::all_supported_formats( formats ); - -for ( std::list ::const_iterator f = formats.begin(); f != formats.end(); ++f ) -{ -// capture_format_menu->add( *f, FL_MENU_RADIO, 0, 0, 0 ); -//; - char pat[256]; - snprintf( pat, sizeof( pat ), "&Project/Se&ttings/Capture Format/%s", *f ); - - menubar->add( pat, 0, &TLE::capture_format_cb, this, FL_MENU_RADIO ); -} - -menubar->picked( menubar->find_item( "&Project/Se&ttings/Capture Format/Wav 24" ) ); - -char *path; -asprintf( &path, "%s/options", user_config_dir ); -((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Options" ), path ); -free( path ); - - -menubar->add( "&Timeline", 0, 0, const_cast< Fl_Menu_Item *>( timeline->menu->menu() ), FL_SUBMENU_POINTER ); - - -// save a copy of the project settings menu so that we can restore the defaults later -{ - char path[512]; - snprintf( path, sizeof( path ), "%s/%s", user_config_dir, ".default_project_settings" ); - - ((Fl_Menu_Settings*)menubar)->dump( menubar->find_item( "&Project/Se&ttings" ), path ); -} - - -Loggable::progress_callback( &TLE::progress_cb, this );} {} - } - Function {make_window()} {open - } { - Fl_Window main_window { - label {Non Timeline} - callback {if ( Fl::event_key() != FL_Escape ) - timeline->command_quit();} open - xywh {204 266 1025 770} type Double resizable - code0 {o->xclass( APP_NAME );} - class TLE_Window size_range {947 300 0 0} visible - } { - Fl_Group {} {open - xywh {0 -53 1025 126} box FLAT_BOX - } { - Fl_Menu_Bar menubar {open - private xywh {0 0 1025 25} - } { - Submenu {} { - label {&Project} open - xywh {5 5 74 25} - } { - MenuItem {} { - label {&Info} - callback {Project_Info_Dialog pi; - -pi.run();} - xywh {5 5 40 25} deactivate - } - Submenu {} { - label {Se&ttings} open - xywh {25 25 74 25} - } { - MenuItem {} { - label {&Follow Playhead} - callback {Timeline::follow_playhead = menu_picked_value( o );} - xywh {45 45 40 25} type Toggle value 1 - } - MenuItem {} { - label {&Center Playhead} - callback {Timeline::center_playhead = menu_picked_value( o );} - xywh {55 55 40 25} type Toggle value 1 - } - Submenu {} { - label {&Snap to} open - xywh {25 25 74 25} - } { - MenuItem {} { - label Bars - callback {Timeline::snap_to = Timeline::Bars;} - xywh {25 25 40 25} type Radio value 1 - } - MenuItem {} { - label Beats - callback {Timeline::snap_to = Timeline::Beats;} - xywh {35 35 40 25} type Radio - } - MenuItem {} { - label Off - callback {Timeline::snap_to = Timeline::None;} - xywh {45 45 40 25} type Radio - } - } - MenuItem {} { - label {Magnetic snap} - callback {Timeline::snap_magnetic = menu_picked_value( o );} - xywh {35 35 40 25} type Toggle value 1 - } - Submenu {} { - label {Capture Format} open - xywh {25 25 74 25} - } {} - MenuItem {} { - label {Playback Latency Compensation} - callback {Timeline::playback_latency_compensation = menu_picked_value( o );} selected - xywh {55 55 40 25} type Toggle - } - } - MenuItem {} { - label {&New} - callback {save_timeline_settings(); - - - char *result_path; - - char *default_path = read_line( user_config_dir, "default_path" ); - result_path = default_path; - - char *path = new_project_chooser( &result_path ); - - if ( path ) - { - if ( ! Project::create( path, NULL ) ) - fl_alert( "Error creating project!" ); - free( path ); - } - - if ( result_path != default_path ) - free(default_path); - - if ( result_path ) - { - write_line( user_config_dir, "default_path", result_path ); - free( result_path ); - } - - -load_timeline_settings(); - -update_menu(); - -main_window->redraw();} - xywh {5 5 40 25} - } - MenuItem {} { - label {&Open} - callback {char *path = read_line( user_config_dir, "default_path" ); - -const char *name = fl_dir_chooser( "Open Project", path ); - -free( path ); - -open( name );} - xywh {15 15 40 25} - } - MenuItem {} { - label {&Compact} - callback {int n = fl_choice( "Compacting will replace the project history with a snapshot of the current state.\\nYou will not be able to use Undo to go back beyond this point.\\n\\nThis operation is irreversible!", NULL, "&Cancel", "Pr&ocede with compaction" ); - -if ( n != 2 ) - return; - -Project::compact();} - xywh {25 25 40 25} - } - Submenu {} { - label {I&mport} open - xywh {20 20 74 25} - } { - MenuItem {} { - label {Import Ardour Session} - callback {if ( !Project::open() ) -{ - fl_alert( "You must create a new project before importing" ); - return; -} - -if ( timeline->ntracks() ) -{ - fl_alert( "You can only import into an empty session!" ); - return; -} - - -pid_t pid; -if ( ! (pid = fork()) ) -{ - exit( system( "import-ardour-session_gui" ) ); -} - -char *path = strdup( Project::path() ); - -Project::close(); - -int status; - -while ( 0 == waitpid( pid, &status, WNOHANG ) ) -{ - Fl::wait(0.2); -} - -Project::open(path); - -free(path);} - xywh {20 20 40 25} - } - } - Submenu {} { - label {&Export} open - xywh {5 5 74 25} hide deactivate - } { - MenuItem {} { - label Project - xywh {5 5 40 25} - } - MenuItem {} { - label Range - xywh {15 15 40 25} - } - } - MenuItem {} { - label {&Quit} - callback {quit()} - xywh {45 45 40 25} shortcut 0x40071 - } - } - Submenu {} { - label {&Edit} open - xywh {5 5 74 25} - } { - MenuItem {} { - label Undo - callback {timeline->command_undo();} - xywh {5 5 40 25} shortcut 0x4007a divider - } - MenuItem {} { - label {Select None} - callback {timeline->select_none();} - xywh {15 15 40 25} shortcut 0x50061 - } - MenuItem {} { - label {Delete Selected} - callback {timeline->delete_selected();} - xywh {25 25 40 25} shortcut 0xffff - } - } - Submenu {} { - label {T&ransport} open - xywh {5 5 74 25} - } { - MenuItem {} { - label Start - callback {transport->locate( 0 );} - xywh {5 5 40 25} shortcut 0xff50 - } - MenuItem {} { - label End - callback {transport->locate( timeline->length() );} - xywh {15 15 40 25} shortcut 0xff57 - } - MenuItem {} { - label {Play/Stop} - callback {transport->toggle();} - xywh {25 25 40 25} shortcut 0x20 - } - MenuItem {} { - label Record - callback {transport->toggle_record();} - xywh {45 45 40 25} shortcut 0x10072 - } - } - MenuItem {} { - label {&Timeline} - xywh {5 5 40 25} - } - Submenu {} { - label {&View} open - xywh {5 5 74 25} - } { - Submenu {} { - label {&Zoom} open - xywh {5 5 74 25} - } { - MenuItem {} { - label {&In} - callback {timeline->zoom_in();} - xywh {25 25 40 25} shortcut 0x2b - } - MenuItem {} { - label {&Out} - callback {timeline->zoom_out();} - xywh {35 35 40 25} shortcut 0x5f - } - MenuItem {} { - label {&Fit} - callback {timeline->zoom_fit();} - xywh {15 15 40 25} shortcut 0x3d divider - } - MenuItem {} { - label {1 sec.} - callback {timeline->zoom( 1 );} - xywh {15 15 40 25} shortcut 0x31 - } - MenuItem {} { - label {1 min.} - callback {timeline->zoom( 60 );} - xywh {25 25 40 25} shortcut 0x32 - } - MenuItem {} { - label {1 hour.} - callback {timeline->zoom( 60 * 60 );} - xywh {35 35 40 25} shortcut 0x33 - } - } - MenuItem {} { - label {&Theme} - callback {fl_theme_chooser();} - xywh {15 15 40 24} - code0 {\#include "FL/Fl_Theme_Chooser.H"} - } - } - Submenu {} { - label {&Options} open - xywh {5 5 74 25} divider - } { - Submenu {} { - label {&Display} open - xywh {15 15 74 25} - } { - Submenu {} { - label {&Timeline} open - xywh {15 15 74 25} - } { - MenuItem {} { - label {&Measure lines} - callback {Timeline::draw_with_measure_lines = menu_picked_value( o ); - -timeline->redraw();} - xywh {15 15 40 25} type Toggle value 1 - } - MenuItem {} { - label {&Cursor Overlay} - callback {Timeline::draw_with_cursor_overlay = menu_picked_value( o ); - -timeline->redraw();} - xywh {15 14 40 25} type Toggle value 1 - } - } - Submenu {} { - label {&Waveform} open - xywh {15 15 74 25} - } { - MenuItem {} { - label Fill - callback {Waveform::fill = menu_picked_value( o ); - -timeline->redraw();} - xywh {25 25 40 25} type Toggle value 1 - } - MenuItem {} { - label Outline - callback {Waveform::outline = menu_picked_value( o ); - -timeline->redraw();} - xywh {45 45 40 25} type Toggle value 1 - } - MenuItem {} { - label {Vary color} - callback {Waveform::vary_color = menu_picked_value( o ); - -timeline->redraw();} - xywh {35 35 40 25} type Toggle value 1 - } - } - Submenu {} { - label {&Region} open - xywh {15 15 74 25} - } { - MenuItem {} { - label {Filled fades} - xywh {45 45 40 25} type Toggle value 1 - } - MenuItem {} { - label {Inherit track color} - callback {Audio_Region::inherit_track_color = menu_picked_value( o ); - -timeline->redraw();} - xywh {55 55 40 25} type Toggle value 1 - } - MenuItem {} { - label {Show box} - callback {Audio_Region::show_box = menu_picked_value( o ); - -timeline->redraw();} - xywh {55 55 40 25} type Toggle value 1 - } - } - Submenu {} { - label {&Control Sequence} open - xywh {15 15 74 25} - } { - MenuItem {} { - label Ruled - callback {Control_Sequence::draw_with_grid = menu_picked_value( o ); - -timeline->redraw();} - xywh {55 55 40 25} type Toggle value 1 - } - } - Submenu {} { - label {&Track} open - xywh {15 15 74 25} - } { - MenuItem {} { - label {Colored tracks} - callback {Track::colored_tracks = menu_picked_value( o ); - -timeline->redraw();} - xywh {45 45 40 25} type Toggle value 1 - } - } - } - Submenu {} { - label {&Behavior} open - xywh {5 5 74 25} - } { - Submenu {} { - label {&Transport} open - xywh {5 5 74 25} - } { - MenuItem {} { - label {Stop Disables Record} - callback {transport->stop_disables_record( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE );} - xywh {10 10 40 25} type Toggle value 1 - } - MenuItem {} { - label {Loop Playback} - callback {transport->loop_enabled( ( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE )) ;} - xywh {10 10 40 25} type Toggle - } - MenuItem {} { - label {Automatically Create Takes} - callback {transport->automatically_create_takes( ( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE ));} - xywh {10 10 40 25} type Toggle - } - } - } - } - Submenu {} { - label {&Help} open - xywh {5 5 74 25} - } { - MenuItem {} { - label {&Manual} - callback {show_help_dialog( "MANUAL" );} - xywh {15 15 40 25} divider - } - MenuItem {} { - label {&About} - callback {About_Dialog ab( PIXMAP_PATH "/non-timeline/icon-256x256.png" ); - - ab.logo_box->label( VERSION ); - - ab.title->label( "Non Timeline" ); - - ab.copyright->label( "Copyright (C) 2008-2013 Jonathan Moore Liles" ); - ab.credits->label( "Non Timeline was written from scratch by\\nJonathan Moore Liles for his own use\\n(see the manual).\\n\\nNobody planned. Nobody helped.\\nYou can help now by donating time, money,\\nand/or replacing the rest of Linux Audio\\nwith fast, light, reliable alternatives.\\n" ); - - ab.website_url->label( "http://non.tuxfamily.org" ); - -ab.run();} - xywh {5 5 40 25} - } - } - } - Fl_Pack {} {open - xywh {1 27 584 46} type HORIZONTAL - code0 {o->spacing( 10 );} - } { - Fl_Box {} { - label {} - xywh {5 28 290 44} color 30 - code0 {transport = o;} - code1 {o->labeltype( FL_NO_LABEL );} - class Transport - } - Fl_Pack clocks_pack {open - private xywh {295 30 290 41} type HORIZONTAL - code0 {o->spacing( 2 );} - } { - Fl_Box {} { - label PLAYHEAD - private xywh {301 30 137 41} box FLAT_BOX color 47 - code0 {o->type( Clock::HMS );} - code1 {o->run( &transport->frame );} - class Clock - } - Fl_Box {} { - label PLAYHEAD - xywh {440 30 137 41} box FLAT_BOX color 47 - code0 {o->type( Clock::BBT );} - code1 {o->run( &transport->frame );} - class Clock - } - } - } - Fl_Box {} { - label {} - xywh {585 32 155 40} resizable - code0 {o->labeltype( FL_NO_LABEL );} - } - Fl_Group {} {open - xywh {850 23 175 50} - } { - Fl_Box {} { - label {capture:} - xywh {910 27 56 14} labelsize 10 align 24 - } - Fl_Box {} { - label {playback:} - xywh {910 43 56 14} labelsize 10 align 24 - } - Fl_Box {} { - label {DSP:} - xywh {910 57 56 14} labelsize 10 align 24 - } - Fl_Box {} { - label filesystem - xywh {855 28 55 18} labelsize 10 align 16 - } - Fl_Progress capture_buffer_progress { - label {50%} - private xywh {965 27 60 14} selection_color 0 labelsize 10 - } - Fl_Progress cpu_load_progress { - label {50%} - private xywh {965 57 60 14} selection_color 0 labelsize 9 - } - Fl_Progress playback_buffer_progress { - label {50%} - private xywh {965 42 60 14} selection_color 0 labelsize 10 - } - Fl_Progress disk_usage_progress { - label {50%} - private xywh {855 43 55 28} selection_color 0 labelsize 10 - code0 {o->type( FL_VERTICAL );} - } - } - Fl_Group {} {open - xywh {740 31 115 40} - } { - Fl_Button solo_blinker { - label SOLO - xywh {800 33 50 15} box BORDER_BOX down_box BORDER_BOX color 74 selection_color 92 labelfont 1 labelsize 11 labelcolor 32 - code0 {\#include "FL/Fl_Blink_Button.H"} - code1 {o->box( FL_ASYM_BOX );} - code2 {o->down_box( FL_ASYM_BOX );} - code3 {o->ignore_input( true );} - class Fl_Blink_Button - } - Fl_Button rec_blinker { - label REC - xywh {800 53 50 15} box BORDER_BOX down_box BORDER_BOX color 72 selection_color 88 labelfont 1 labelsize 11 labelcolor 32 - code0 {\#include "FL/Fl_Blink_Button.H"} - code1 {o->box( FL_ASYM_BOX );} - code2 {o->down_box( FL_ASYM_BOX );} - code3 {o->ignore_input( true );} - class Fl_Blink_Button - } - Fl_Button selected_blinker { - label SEL - xywh {745 53 50 15} box BORDER_BOX down_box BORDER_BOX color 13 selection_color 5 labelfont 1 labelsize 11 labelcolor 32 - code0 {\#include "FL/Fl_Blink_Button.H"} - code1 {o->box( FL_ASYM_BOX );} - code2 {o->down_box( FL_ASYM_BOX );} - code3 {o->ignore_input( true );} - class Fl_Blink_Button - } - Fl_Button seek_blinker { - label SEEK - xywh {745 33 50 15} box BORDER_BOX down_box BORDER_BOX color 10 selection_color 2 labelfont 1 labelsize 11 labelcolor 32 - code0 {\#include "FL/Fl_Blink_Button.H"} - code1 {o->box( FL_ASYM_BOX );} - code2 {o->down_box( FL_ASYM_BOX );} - code3 {o->ignore_input( true );} - class Fl_Blink_Button - } - } - Fl_Box stats_box { - label {} - xywh {745 0 235 25} labelsize 13 labelcolor 53 align 88 - } - Fl_Button sm_blinker { - label SM - xywh {985 6 35 15} box ROUNDED_BOX down_box ROUNDED_BOX color 45 selection_color 93 labelfont 3 labelcolor 39 deactivate - class Fl_Button - } - } - Fl_Group progress_group {open - xywh {295 352 450 79} hide - } { - Fl_Progress progress { - label {0%} - private xywh {295 394 450 37} box ROUNDED_BOX selection_color 55 labelfont 1 labelsize 22 - } - Fl_Box {} { - label {Loading...} - xywh {295 362 450 31} labelfont 1 labelsize 17 align 18 - } - } - Fl_Box {} { - label {} - xywh {0 75 1025 692} box FLAT_BOX color 47 labeltype NO_LABEL labelsize 100 resizable - code0 {timeline = o;} - class Timeline - } - Fl_Box project_name { - label {} - private xywh {440 0 305 24} labeltype SHADOW_LABEL labelfont 2 - code0 {o->label( Project::name() );} - } - } - } - Function {menu_picked_value( const Fl_Menu_ *m )} {private return_type {static int} - } { - code {return m->menu()[ m->value() ].flags & FL_MENU_VALUE;} {} - } - Function {find_item( Fl_Menu_ *menu, const char *path )} {private return_type {static Fl_Menu_Item *} - } { - code {return const_cast(menu->find_item( path ));} {} - } - decl {static void menubar_cb ( void *v )} {private local - } - decl {void menubar_cb ( void )} {private local - } - Function {update_menu()} {private - } { - code {Fl_Menu_Bar *m = menubar; - -if ( ! Project::open() ) -{ - find_item( m, "&Project/&Export" )->deactivate(); - find_item( m, "&Project/&Compact" )->deactivate(); - find_item( m, "&Project/&Info" )->deactivate(); - - find_item( m, "&Project/Se&ttings" )->deactivate(); - find_item( m, "&Timeline" )->deactivate(); - - timeline->deactivate(); - transport->deactivate(); -} -else -{ - find_item( m, "&Project/&Export" )->activate(); - find_item( m, "&Project/&Compact" )->activate(); - find_item( m, "&Project/&Info" )->activate(); - - find_item( m, "&Project/Se&ttings" )->activate(); - find_item( m, "&Timeline" )->activate(); - - timeline->activate(); - transport->activate(); -} - -m->redraw(); -project_name->redraw();} {} - } - Function {update_progress( Fl_Progress *p, char *s, float v )} {private return_type {static void} - } { - code {if ( p->value() != v ) -{ -p->value( v ); - -snprintf( s, 5, "%d%%", (int)v ); - -p->label( s ); - -}} {} - } - Function {update_status()} {open private - } { - code {static char cbp[5], pbp[5], clp[5], dup[5]; - -update_progress( capture_buffer_progress, cbp, timeline->total_input_buffer_percent() ); -update_progress( playback_buffer_progress, pbp, timeline->total_output_buffer_percent() ); -update_progress( cpu_load_progress, clp, engine ? engine->cpu_load() : 0 ); - -if ( Project::open() ) - update_progress( disk_usage_progress, dup, percent_used( Project::path() ) ); -else - update_progress( disk_usage_progress, dup, 0 ); - -if ( timeline->total_capture_xruns() ) - capture_buffer_progress->selection_color( FL_RED ); - -if ( timeline->total_playback_xruns() ) - playback_buffer_progress->selection_color( FL_RED ); - -static char stats[100]; - -if ( engine && ! engine->zombified() ) -{ -snprintf( stats, sizeof( stats ), "latency: %.1fms, xruns: %d", - engine->frames_to_milliseconds( engine->system_latency() ), - engine->xruns() ); -} -else -{ - snprintf( stats, sizeof( stats ), "%s", "DISCONNECTED" ); -} - -stats_box->label( stats ); - -static bool zombie = false; - -if ( engine && engine->zombified() && ! zombie ) -{ - zombie = true; - fl_alert( "Disconnected from JACK!" ); -} - -solo_blinker->value( Track::soloing() ); - -if ( transport->punch_enabled() && timeline->range_start() != timeline->range_end() ) - rec_blinker->value( transport->rolling && - transport->rec_enabled() && - transport->frame >= timeline->range_start() && - transport->frame <= timeline->range_end() ); -else - rec_blinker->value( transport->rolling && transport->rec_enabled() ); - -sm_blinker->value( timeline->session_manager_name() != NULL ); -sm_blinker->tooltip( timeline->session_manager_name() ); -selected_blinker->value( timeline->nselected() ); -seek_blinker->value( timeline->seek_pending() ); - -if ( timeline->session_manager_name() != NULL ) -{ - find_item( menubar, "&Project/&New" )->deactivate(); - find_item( menubar, "&Project/&Open" )->deactivate(); -} - -// project_name->redraw();} {} - } - Function {update_cb( void *v )} {open private return_type {static void} - } { - code {Fl::repeat_timeout( STATUS_UPDATE_FREQ, update_cb, v ); - -((TLE*)v)->update_status();} {} - } - Function {capture_format_cb( Fl_Widget *, void *v )} {private return_type {static void} - } { - code {((TLE*)v)->capture_format_cb();} {} - } - Function {capture_format_cb()} {private return_type void - } { - code {Fl_Menu_ *o = menubar; - -Track::capture_format = o->menu()[ o->value() ].label();} {} - } - Function {progress_cb( int p, void *arg )} {private return_type {static void} - } { - code {((TLE*)arg)->progress_cb( p );} {} - } - Function {progress_cb( int p )} {private return_type void - } { - code {if ( ! progress_group->visible() ) -{ - timeline->hide(); - progress_group->show(); -} -else if ( 0 == p ) -{ - timeline->show(); - progress_group->hide(); -} - -// never allow drawing timeline while loading, as this would cause lock recursion. -if ( timeline->visible() ) - return; - -static int oldp; -static char pat[10]; - -if ( p != oldp ) -{ - oldp = p; - nsm_send_progress( nsm, p / 100.0f ); - update_progress( progress, pat, p ); - - progress->redraw(); - - Fl::check(); -}} {} - } - Function {show_help_dialog( const char *file )} {open private return_type {static void} - } { - code {char pat[256]; - -snprintf( pat, 256, "file://%s/non-timeline/%s.html", DOCUMENT_PATH, file ); - -open_url( pat );} {} - } -} - -Function {set_theme_dark()} {C return_type void -} { - code {Fl::background2( 100, 100, 100 ); - Fl::background( 50, 50, 50 ); - Fl::foreground( 255, 255, 255 );} {} -} - -class Project_Info_Dialog {open -} { - Function {Project_Info_Dialog()} {open - } { - code {make_window();} {} - } - Function {run()} {open return_type void - } { - code {window->show(); - -while ( window->shown() ) - Fl::wait();} {} - } - Function {make_window()} {open - } { - Fl_Window window { - label {Project info} - callback {o->hide(); - -if ( logo_box->image() ) -{ - ((Fl_Shared_Image*)logo_box->image())->release(); - logo_box->image( NULL ); -}} open - private xywh {1195 197 520 710} type Double modal visible - } { - Fl_Group {} {open - xywh {25 30 470 75} - } { - Fl_Value_Output {} { - label {Sample Rate} - xywh {35 30 90 25} labeltype SHADOW_LABEL align 1 - code0 {o->value( timeline->sample_rate() );} - } - Fl_Output {} { - label {Size of Journal} - xywh {175 30 100 25} box UP_BOX labeltype SHADOW_LABEL align 1 - code0 {static char pat[40];} - code1 {snprintf( pat, sizeof( pat ), "%.1fK", size( "history" ) / (float)1024 );} - code2 {o->value( pat );} - code3 {\#include "file.h"} - } - Fl_Output {} { - label {Created On} - xywh {315 30 180 25} box UP_BOX labeltype SHADOW_LABEL align 1 textfont 11 textsize 12 - code0 {o->value( Project::created_on() );} - } - Fl_Output {} { - label Length - xywh {25 80 115 25} box BORDER_BOX color 47 align 1 textcolor 71 - code0 {char pat[40];} - code1 {Clock::frame_to_HMS( pat, sizeof( pat ), timeline->length() );} - code2 {o->value( pat );} - } - Fl_Value_Output {} { - label Tracks - xywh {195 80 55 25} align 1 - code0 {o->value( timeline->ntracks() );} - } - Fl_Output {} { - label {Last Modified On} - xywh {315 80 180 25} box UP_BOX labeltype SHADOW_LABEL align 1 textfont 11 textsize 12 - code0 {time_t t = modification_time( "history" );} - code1 {static char s[40];} - code2 {ctime_r( &t, s ); s[ strlen( s ) - 1 ] = 0;} - code3 {o->value( s );} - } - } - Fl_Box logo_box { - label {} - private xywh {18 117 485 268} color 53 labelfont 1 labelsize 18 align 16 - code0 {o->image( Fl_Shared_Image::get( PIXMAP_PATH "/non-timeline/icon-256x256.png" ) );} - code1 {o->label( NULL );} - } - Fl_Text_Editor notes_field { - label {Notes:} - private xywh {20 420 480 245} color 47 selection_color 31 textsize 18 textcolor 92 - code0 {o->buffer( new Fl_Text_Buffer() );} - code1 {o->buffer()->loadfile( "notes" );} - } - Fl_Button {} { - label {&Save} - callback {notes_field->buffer()->savefile( "notes" ); - -window->do_callback();} - xywh {422 676 74 25} - } - Fl_Button {} { - label {&Discard} - callback {window->do_callback();} - xywh {332 676 74 25} - } - } - } -} diff --git a/timeline/src/Tempo_Point.C b/timeline/src/Tempo_Point.C deleted file mode 100644 index 5848ffc..0000000 --- a/timeline/src/Tempo_Point.C +++ /dev/null @@ -1,174 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Tempo_Point.H" -#include "Tempo_Sequence.H" -#include "Timeline.H" // for timeline->tempo_track - - - -Tempo_Point::Tempo_Point ( ) -{ - timeline->tempo_track->add( this ); -} - -Tempo_Point::Tempo_Point ( nframes_t when, float bpm ) -{ - _tempo = bpm; - - _make_label(); - - timeline->tempo_track->add( this ); - - start( when ); - - log_create(); -} - -Tempo_Point::~Tempo_Point ( ) -{ - timeline->tempo_track->remove( this ); - log_destroy(); -} - - - -void -Tempo_Point::get ( Log_Entry &e ) const -{ -// Sequence_Point::get( e ); - - e.add( ":start", start() ); - e.add( ":tempo", _tempo ); -} - -void -Tempo_Point::set ( Log_Entry &e ) -{ - - Sequence_Point::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":tempo" ) ) - _tempo = atof( v ); - -/* /\* FIXME: we need to add this to the time track on creation!!! *\/ */ -/* timeline->tempo_track->add( this ); */ - - } - - sequence()->handle_widget_change( start(), length() ); - - _make_label(); -} - -int -Tempo_Point::handle ( int m ) -{ - Logger log( this ); - - if ( m == FL_PUSH && Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) ) - { - float t = _tempo; - edit( &t ); - tempo( t ); - return 0; - } - - return Sequence_Point::handle( m ); -} - - -#include -#include - - -class Tempo_Point_Editor : public Fl_Menu_Window -{ - - /* not permitted */ - Tempo_Point_Editor ( const Tempo_Point_Editor &rhs ); - Tempo_Point_Editor & operator = ( const Tempo_Point_Editor &rhs ); - - float *_tempo; - Fl_Float_Input *_fi; - - bool _sucess; - -public: - - Tempo_Point_Editor ( float *tempo ) : Fl_Menu_Window( 75, 58, "Edit Tempo" ) - { - _sucess = false; - _tempo = tempo; - - set_modal(); - - Fl_Float_Input *fi = _fi = new Fl_Float_Input( 12, 0 + 24, 50, 24, "Tempo:" ); - fi->align( FL_ALIGN_TOP ); - fi->when( FL_WHEN_NOT_CHANGED | FL_WHEN_ENTER_KEY ); - fi->callback( &Tempo_Point_Editor::enter_cb, (void*)this ); - - char pat[10]; - snprintf( pat, sizeof( pat ), "%.1f", *tempo ); - - fi->value( pat ); - - end(); - - show(); - - while ( shown() ) - Fl::wait(); - } - - static void - enter_cb ( Fl_Widget *, void *v ) - { - ((Tempo_Point_Editor*)v)->enter_cb(); - } - - void - enter_cb ( void ) - { - sscanf( _fi->value(), "%f", _tempo ); - _sucess = true; - hide(); - } - - bool - sucess ( void ) - { - return _sucess; - } -}; - - -bool -Tempo_Point::edit ( float *tempo ) -{ - Tempo_Point_Editor ti( tempo ); - - return ti.sucess(); -} diff --git a/timeline/src/Tempo_Point.H b/timeline/src/Tempo_Point.H deleted file mode 100644 index 8dd88d0..0000000 --- a/timeline/src/Tempo_Point.H +++ /dev/null @@ -1,79 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence_Point.H" -// #include "Tempo_Sequence.H" - -class Tempo_Point : public Sequence_Point -{ - float _tempo; - - BBT _bbt; - - void - _make_label ( void ) - { - char l[10]; - - snprintf( l, sizeof(l), "%.1f", _tempo ); - - label( l ); - } - -protected: - -// const char *class_name ( void ) { return "Tempo_Point"; } - - virtual void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - Tempo_Point ( ); - -public: - - LOG_CREATE_FUNC( Tempo_Point ); - SEQUENCE_WIDGET_CLONE_FUNC( Tempo_Point ); - - static bool edit ( float *tempo ); - - const BBT * bbt ( void ) const { return &_bbt; } - - Tempo_Point ( nframes_t when, float bpm ); - - virtual ~Tempo_Point ( ); - - Tempo_Point ( const Tempo_Point &rhs ) : Sequence_Point( rhs ) - { - _tempo = rhs._tempo; - _bbt = rhs._bbt; - - log_create(); - } - - - float tempo ( void ) const - { return _tempo; } - void tempo ( float v ) - { if ( v != _tempo ) { _tempo = v; _make_label(); timeline->redraw(); } } - - int handle ( int m ); -}; diff --git a/timeline/src/Tempo_Sequence.C b/timeline/src/Tempo_Sequence.C deleted file mode 100644 index 50c16b3..0000000 --- a/timeline/src/Tempo_Sequence.C +++ /dev/null @@ -1,79 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Tempo_Sequence.H" -#include "Track.H" - -Tempo_Sequence::Tempo_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) -{ - box( FL_FLAT_BOX ); - - { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); - o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - o->labelsize( 12 ); - o->labeltype( FL_NORMAL_LABEL ); - o->label( "Tempo" ); - Fl_Group::add( o ); - } - - resizable(0); -} - -void -Tempo_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) -{ - Sequence::handle_widget_change( start, length ); - - sort(); - timeline->update_tempomap(); - timeline->redraw(); -} - -int -Tempo_Sequence::handle ( int m ) -{ - int r = Sequence::handle( m ); - - if ( r ) - return r; - - switch ( m ) - { - case FL_PUSH: - if ( Fl::event_button1() ) - { - static float t = 120.0f; - - if ( Tempo_Point::edit( &t ) ) - { - timeline->sequence_lock.wrlock(); - - new Tempo_Point( timeline->x_to_offset( Fl::event_x() ), t ); - - timeline->sequence_lock.unlock(); - - timeline->redraw(); - } - return 0; - } - default: - return 0; - - } -} diff --git a/timeline/src/Tempo_Sequence.H b/timeline/src/Tempo_Sequence.H deleted file mode 100644 index 61f6498..0000000 --- a/timeline/src/Tempo_Sequence.H +++ /dev/null @@ -1,43 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include "Sequence.H" -#include "Tempo_Point.H" - -class Tempo_Sequence : public Sequence -{ - -protected: - - /* not used */ - void get ( Log_Entry & ) const { } - void set ( Log_Entry & ) { } - -public: - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - - Tempo_Sequence ( int X, int Y, int W, int H ); - - void handle_widget_change ( nframes_t start, nframes_t length ); - int handle ( int m ); - -}; diff --git a/timeline/src/Time_Point.C b/timeline/src/Time_Point.C deleted file mode 100644 index 002c38c..0000000 --- a/timeline/src/Time_Point.C +++ /dev/null @@ -1,203 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Time_Point.H" -#include "Time_Sequence.H" -#include "Timeline.H" // for timeline->time_track - - - -Time_Point::Time_Point ( ) : _time( 4, 4 ) -{ - timeline->time_track->add( this ); -} - -Time_Point::Time_Point ( nframes_t when, int bpb, int note ) : _time( bpb, note ) -{ - _make_label(); - - timeline->time_track->add( this ); - - start( when ); - - log_create(); -} - -Time_Point::Time_Point ( const Time_Point &rhs ) : Sequence_Point( rhs ) -{ - _time = rhs._time; - - log_create(); - -} - -Time_Point::~Time_Point ( ) -{ - timeline->time_track->remove( this ); - - log_destroy(); -} - - - -void -Time_Point::get ( Log_Entry &e ) const -{ -// Sequence_Point::get( e ); - - e.add( ":start", start() ); - e.add( ":beats_per_bar", _time.beats_per_bar ); - e.add( ":beat_type", _time.beat_type ); -} - -void -Time_Point::set ( Log_Entry &e ) -{ - - Sequence_Point::set( e ); - - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":beats_per_bar" ) ) - _time.beats_per_bar = atoi( v ); - else if ( ! strcmp( s, ":beat_type" ) ) - _time.beat_type = atoi( v ); - -/* /\* FIXME: we need to add this to the time track on creation!!! *\/ */ -/* timeline->time_track->add( this ); */ - - } - - sequence()->handle_widget_change( start(), length() ); - - _make_label(); -} - -int -Time_Point::handle ( int m ) -{ - Logger log( this ); - - if ( m == FL_PUSH && Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) ) - { - - time_sig t = _time; - - edit( &t ); - - time( t.beats_per_bar, t.beat_type ); - - return 0; - - } - - return Sequence_Point::handle( m ); -} - -#include -#include - -class Time_Point_Editor : public Fl_Menu_Window -{ - - /* not permitted */ - Time_Point_Editor ( const Time_Point_Editor &rhs ); - Time_Point_Editor & operator = ( const Time_Point_Editor &rhs ); - - time_sig *_sig; - Fl_Int_Input *_beats; - Fl_Int_Input *_beat_type; - - bool _sucess; - -public: - - Time_Point_Editor ( time_sig *sig ) - : Fl_Menu_Window( 150, 110, "Edit Time" ) - { - _sig = sig; - - set_modal(); - - { - Fl_Int_Input *o = _beats = new Fl_Int_Input( 50, 0 + 24, 50, 24, "Beats Per Bar:" ); - o->align( FL_ALIGN_TOP ); - o->when( FL_WHEN_NOT_CHANGED | FL_WHEN_ENTER_KEY ); - o->callback( &Time_Point_Editor::enter_cb, (void*)this ); - } - - { - Fl_Int_Input *o = _beat_type = new Fl_Int_Input( 50, 0 + 75, 50, 24, "Beat Type:" ); - o->align( FL_ALIGN_TOP ); - o->when( FL_WHEN_NOT_CHANGED | FL_WHEN_ENTER_KEY ); - o->callback( &Time_Point_Editor::enter_cb, (void*)this ); - } - - char pat[10]; - snprintf( pat, sizeof( pat ), "%d", _sig->beats_per_bar ); - - _beats->value( pat ); - - snprintf( pat, sizeof( pat ), "%d", _sig->beat_type ); - - _beat_type->value( pat ); - - end(); - - show(); - - while ( shown() ) - Fl::wait(); - } - - static void - enter_cb ( Fl_Widget *, void *v ) - { - ((Time_Point_Editor*)v)->enter_cb(); - } - - void - enter_cb ( void ) - { - _sig->beats_per_bar = atoi( _beats->value() ); - _sig->beat_type = atoi( _beat_type->value() ); - - _sucess = true; - - hide(); - } - - bool - sucess ( void ) - { - return _sucess; - } -}; - -bool -Time_Point::edit ( time_sig *sig ) -{ - Time_Point_Editor ti( sig ); - - return ti.sucess(); -} diff --git a/timeline/src/Time_Point.H b/timeline/src/Time_Point.H deleted file mode 100644 index 79665aa..0000000 --- a/timeline/src/Time_Point.H +++ /dev/null @@ -1,87 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence_Point.H" -#include "Loggable.H" - -struct time_sig -{ - int beats_per_bar; - int beat_type; - - time_sig ( ) : beats_per_bar( 0 ), beat_type( 0 ) - { - } - - time_sig ( int bpb, int note ) : beats_per_bar( bpb ), beat_type( note ) - { - } -}; - -class Time_Point : public Sequence_Point -{ - time_sig _time; - - void - _make_label ( void ) - { - char l[10]; - - snprintf( l, sizeof(l), "%d/%d", _time.beats_per_bar, _time.beat_type ); - - label( l ); - } - - -protected: - -// const char *class_name ( void ) { return "Time_Point"; } - - virtual void get ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - Time_Point ( ); - -public: - - LOG_CREATE_FUNC( Time_Point ); - SEQUENCE_WIDGET_CLONE_FUNC( Time_Point ); - - static bool edit ( time_sig *sig ); - - Time_Point ( nframes_t when, int bpb, int note ); - Time_Point ( const Time_Point &rhs ); - - ~Time_Point ( ); - - void - time ( int bpb, int note ) - { - _time.beats_per_bar = bpb; _time.beat_type = note; - _make_label(); - redraw(); - } - time_sig time ( void ) const { return _time; } - - int handle ( int m ); - -}; diff --git a/timeline/src/Time_Sequence.C b/timeline/src/Time_Sequence.C deleted file mode 100644 index f877b8a..0000000 --- a/timeline/src/Time_Sequence.C +++ /dev/null @@ -1,82 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include "Time_Sequence.H" -#include "Track.H" -#include - -Time_Sequence::Time_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) -{ - box( FL_FLAT_BOX ); - - { Fl_Box *o = new Fl_Box( X, Y, Track::width(), H ); - o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - o->labelsize( 12 ); - o->labeltype( FL_NORMAL_LABEL ); - o->label( "Time" ); - Fl_Group::add( o ); - } - - resizable(0); -} - - - -void -Time_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) -{ - Sequence::handle_widget_change( start, length ); - - sort(); - timeline->update_tempomap(); - timeline->redraw(); -} - -int -Time_Sequence::handle ( int m ) -{ - int r = Sequence::handle( m ); - - if ( r ) - return r; - - switch ( m ) - { - case FL_PUSH: - if ( Fl::event_button1() ) - { - static time_sig t = time_sig( 4, 4 ); - - if ( Time_Point::edit( &t ) ) - { - timeline->sequence_lock.wrlock(); - - new Time_Point( timeline->x_to_offset( Fl::event_x() ), t.beats_per_bar, t.beat_type ); - - timeline->sequence_lock.unlock(); - - timeline->redraw(); - } - return 0; - } - default: - return 0; - - } -} diff --git a/timeline/src/Time_Sequence.H b/timeline/src/Time_Sequence.H deleted file mode 100644 index 4e71a71..0000000 --- a/timeline/src/Time_Sequence.H +++ /dev/null @@ -1,65 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Sequence.H" -#include "Time_Point.H" - -#include -using std::list; - -class Time_Sequence : public Sequence -{ - -protected: - - /* not used */ - void get ( Log_Entry & ) const { } - void set ( Log_Entry & ) { } - -public: - - Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; } - - Time_Sequence ( int X, int Y, int W, int H ); - - time_sig - time ( nframes_t when ) - { - for ( list ::const_reverse_iterator i = _widgets.rbegin(); - i != _widgets.rend(); i++ ) - { - if ( (*i)->offset() < when ) - return ((Time_Point*)(*i))->time(); - } - - return time_sig( 4, 4 ); - } - - void - time ( nframes_t when, int bpb, int note ) - { - add( new Time_Point( when, bpb, note ) ); - } - - void handle_widget_change ( nframes_t start, nframes_t length ); - int handle ( int m ); -}; diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C deleted file mode 100644 index ccde2a1..0000000 --- a/timeline/src/Timeline.C +++ /dev/null @@ -1,2266 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* This is the Timeline widget, which contains all the tracks and - * provides cursor overlays, scrolling, zooming, measure lines, tempo - * map and just about everything else. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Timeline.H" -#include "Tempo_Sequence.H" -#include "Time_Sequence.H" -#include "Cursor_Sequence.H" -#include "Audio_Sequence.H" -#include "Control_Sequence.H" -#include "Sequence.H" -#include "Annotation_Sequence.H" -#include "Track.H" -#include "Transport.H" - -#include "FL/menu_popup.H" - -#include "const.h" -#include "debug.h" - -/* these headers are just for the NSM support */ -#include "Project.H" -#include "TLE.H" -/* */ - -#include "OSC_Thread.H" -#include "OSC/Endpoint.H" - -#include - -#include -extern nsm_client_t *nsm; - -#define BASE Fl_Group -#define BX this->x() -#define BY this->y() - - - -bool Timeline::draw_with_measure_lines = true; -bool Timeline::draw_with_cursor_overlay = true; -Timeline::snap_e Timeline::snap_to = Bars; -bool Timeline::snapping_on_hold = false; -bool Timeline::snap_magnetic = true; -bool Timeline::follow_playhead = true; -bool Timeline::center_playhead = true; -bool Timeline::playback_latency_compensation = false; - -const float UPDATE_FREQ = 1.0f / 18.0f; - -extern const char *instance_name; -extern TLE *tle; - - - -/** return the combined height of all visible children of (veritcal) - pack, /p/. This is necessary because pack sizes are adjusted only - when the relevant areas are exposes. */ -static int -pack_visible_height ( const Fl_Pack *p ) -{ - int th = 0; - - const Fl_Widget* const *w = p->array(); - for ( int i = p->children(); i--; ++w ) - if ( (*w)->visible() ) - th += (*w)->h() + p->spacing(); - - return th; -} - -#define BP fl_begin_polygon() -#define EP fl_end_polygon() -#define vv(x,y) fl_vertex( x, y ) -#define BL fl_begin_line() -#define EL fl_end_line() - -void -draw_full_arrow_symbol ( Fl_Color color ) -{ - /* draw cap */ - fl_color( color ); - - BP; - vv( -1, -1 ); - vv( 0, 1 ); - vv( 1, -1 ); - EP; - - /* draw cap outline */ - fl_color( FL_BLACK ); - - BL; - vv( -1, -1 ); - vv( 0, 1 ); - vv( 1, -1 ); - EL; - -} - - - -class Timeline::Timeline_Panzoomer : public Fl_Panzoomer -{ -public: - Timeline_Panzoomer ( int X,int Y,int W,int H, const char *L=0) - : Fl_Panzoomer(X,Y,W,H) - { - } -protected: - void - draw_background ( int X, int Y,int W, int H ) - { - nframes_t ef = timeline->x_to_ts( _xmax ); - - double ty = Y; - - for ( int i = 0; i < timeline->tracks->children(); i++ ) - { - Track *t = (Track*)timeline->tracks->child( i ); - - Sequence *s = t->sequence(); - - if ( !s ) - continue; - - fl_color( FL_DARK1 ); - - const double scale = (double)H / ( pack_visible_height( timeline->tracks ) ); - -// double th = (double)H / timeline->tracks->children(); - const double th = t->h() * scale; - - fl_line( X, ty, - X + W, ty ); - - for ( list ::const_iterator r = s->_widgets.begin(); - r != s->_widgets.end(); ++r ) - { - fl_rectf( - X + ( W * ( (double)(*r)->start() / ef ) ), - ty, - W * ( (double)(*r)->length() / ef ), - th, - (*r)->actual_box_color()); - } - - fl_font( FL_HELVETICA, th ); - fl_color( FL_FOREGROUND_COLOR ); - fl_draw( t->name(), X, ty, W, th, (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_INSIDE )); - - ty += th; - } - } -}; - - - - - -void -Timeline::redraw_overlay ( void ) -{ - ((Fl_Overlay_Window*)window())->redraw_overlay(); -} - -nframes_t -Timeline::range_start ( void ) const -{ - if ( edit_cursor_track->active_cursor() ) - return edit_cursor_track->active_cursor()->start(); - else - return 0; -} - -nframes_t -Timeline::range_end ( void ) const -{ - if ( edit_cursor_track->active_cursor() ) - return edit_cursor_track->active_cursor()->start() + edit_cursor_track->active_cursor()->length(); - else - return 0; -} - -void -Timeline::range_start ( nframes_t n ) -{ - if ( ! edit_cursor_track->active_cursor() ) - new Cursor_Region( 0, 0, "Edit", NULL ); - - Logger log( edit_cursor_track->active_cursor() ); - - edit_cursor_track->active_cursor()->set_left( n ); -} - -void -Timeline::range_end ( nframes_t n ) -{ - if ( ! edit_cursor_track->active_cursor() ) - new Cursor_Region( 0, 0, "Edit", NULL ); - - Logger log( edit_cursor_track->active_cursor() ); - - edit_cursor_track->active_cursor()->set_right( n ); -} - -/** return first frame of playback (might not be 0) */ -nframes_t -Timeline::playback_home ( void ) const -{ - if ( play_cursor_track->active_cursor() ) - return play_cursor_track->active_cursor()->start(); - else - return 0; -} - -/** return last frame of playback */ -nframes_t -Timeline::playback_end ( void ) const -{ - if ( play_cursor_track->active_cursor() ) - return play_cursor_track->active_cursor()->start() + play_cursor_track->active_cursor()->length(); - else - return length(); -} - -void -Timeline::reset_range ( void ) -{ - delete edit_cursor_track->active_cursor(); -} - -/** callback used by Loggable class to create a snapshot of system - * state. */ -void -Timeline::snapshot ( void ) -{ - tempo_track->log_children(); - time_track->log_children(); - edit_cursor_track->log_children(); - punch_cursor_track->log_children(); - play_cursor_track->log_children(); - - update_track_order(); - - for ( int i = 0; i < tracks->children(); ++i ) - { - ((Track*)tracks->child( i ))->log_children(); - } -} - - -/** recalculate the size of horizontal scrolling area and inform scrollbar */ -void -Timeline::adjust_panzoomer ( void ) -{ - panzoomer->y_value( panzoomer->y_value(), h() - rulers->h() - panzoomer->h(), 0, pack_visible_height( tracks )); - panzoomer->x_value( ts_to_x( xoffset ), /* pos */ - tracks->w() - Track::width(), /* window size */ - 0, /* min */ - max( ts_to_x( length() ), tracks->w() - Track::width() )/* max */ - ); -} - -void -Timeline::cb_scroll ( Fl_Widget *w, void *v ) -{ - ((Timeline*)v)->cb_scroll( w ); -} - -void -Timeline::cb_scroll ( Fl_Widget *w ) -{ - //adjust_panzoomer(); - - if ( panzoomer->zoom_changed() ) - { - nframes_t under_mouse = x_to_offset( Fl::event_x() ); - - _fpp = panzoomer->zoom(); - - panzoomer->x_value( ts_to_x( under_mouse ) ); - - redraw(); - } - - if ( _old_yposition != panzoomer->y_value() ) - { - tracks->position( tracks->x(), track_window->y() - (int)panzoomer->y_value() ); - damage( FL_DAMAGE_SCROLL ); - } - - if ( _old_xposition != x_to_ts( panzoomer->x_value() )) - { - damage( FL_DAMAGE_SCROLL ); - xposition( panzoomer->x_value() ); - } -} - -void -Timeline::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Timeline*)v)->menu_cb( (Fl_Menu_*)w ); -} - -/** ensure that p1 is less than range_end() */ -void -Timeline::fix_range ( void ) -{ - if ( range_start() > range_end() ) - { - nframes_t t = range_end(); - range_end( range_start() ); - range_start( t ); - } -} - -/** set the range to /start/ + /length/ */ -void -Timeline::range ( nframes_t start, nframes_t length ) -{ - range_start( start ); - range_end( start + length ); - - redraw(); -} - -/** create a new take for every armed track */ -void -Timeline::add_take_for_armed_tracks ( void ) -{ - THREAD_ASSERT( UI ); - - track_lock.wrlock(); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->sequence()->_widgets.size() ) - t->sequence( new Audio_Sequence( t ) ); - } - - track_lock.unlock(); -} - -/* coordinates of mouse at time context menu is brought up. */ -static int menu_event_x = 0; -static int menu_event_y = 0; -void -Timeline::menu_cb ( Fl_Menu_ *m ) -{ - if ( ! active_r() ) - return; - - const char *picked = m->mvalue()->label(); - -/* m->item_pathname( picked, sizeof( picked ) ); */ - - DMESSAGE( "%s", picked ); - - if ( ! strcmp( picked, "Add audio track" ) ) - { - /* FIXME: prompt for I/O config? */ - - Loggable::block_start(); - - /* add audio track */ - char *name = get_unique_track_name( "Audio" ); - - Track *t = new Track( name ); - - free( name ); - - Audio_Sequence *o = new Audio_Sequence( t ); - - add_track( t ); - - t->sequence( o ); - - t->take_focus(); - - Loggable::block_end(); - } - else if ( ! strcmp( picked, "Tempo from edit (beat)" ) ) - { - if ( range_start() != range_end() ) - { - fix_range(); - - beats_per_minute( range_start(), sample_rate() * 60 / (float)( range_end() - range_start() ) ); - - range_end( range_start() ); - } - } - else if ( ! strcmp( picked, "Tempo from edit (bar)" ) ) - { - if ( range_start() != range_end() ) - { - fix_range(); - - position_info pi = solve_tempomap( range_start() ); - - beats_per_minute( range_start(), sample_rate() * 60 / (float)( ( range_end() - range_start() ) / pi.beats_per_bar ) ); - - range_end( range_start() ); - } - } - else if ( ! strcmp( picked, "Playhead to mouse" ) ) - { - int X = Fl::event_x() - Track::width(); - - if ( X > 0 ) - { - transport->locate( xoffset + x_to_ts( X ) ); - } - } - else if ( ! strcmp( picked, "Edit start to mouse" ) ) - { - int X = Fl::event_x() - Track::width(); - - if ( X > 0 ) - { - range_start( xoffset + x_to_ts( X ) ); - } - - fix_range(); - - /* FIXME: only needs to damage the location of the old cursor! */ - redraw(); - } - else if ( ! strcmp( picked, "Edit end to mouse" ) ) - { - int X = Fl::event_x() - Track::width(); - - if ( X > 0 ) - { - range_end( xoffset + x_to_ts( X ) ); - } - - fix_range(); - - /* FIXME: only needs to damage the location of the old cursor! */ - redraw(); - } - else if ( ! strcmp( picked, "Playhead left beat" ) ) - { - nframes_t f = transport->frame; - - if ( prev_line( &f ) ) - transport->locate( f ); - } - else if ( ! strcmp( picked, "Playhead right beat" ) ) - { - nframes_t f = transport->frame; - - if ( next_line( &f ) ) - transport->locate( f ); - } - else if ( ! strcmp( picked, "Playhead left bar" ) ) - { - nframes_t f = transport->frame; - - if ( prev_line( &f, true ) ) - transport->locate( f ); - } - else if ( ! strcmp( picked, "Playhead right bar" ) ) - { - nframes_t f = transport->frame; - - if ( next_line( &f, true ) ) - transport->locate( f ); - } - else if ( ! strcmp( picked, "Swap edit start and playhead" ) ) - { - nframes_t t = transport->frame; - - transport->locate( range_start() ); - - range_start( t ); - - redraw(); - } - else if ( ! strcmp( picked, "Swap edit end and playhead" ) ) - { - nframes_t t = transport->frame; - - transport->locate( range_end() ); - - range_end( t ); - - redraw(); - } - else if ( ! strcmp( picked, "Edit start to playhead" ) ) - { - range_start( transport->frame ); - - redraw(); - } - else if ( ! strcmp( picked, "Edit end to playhead" ) ) - { - range_end( transport->frame ); - - redraw(); - } - else if ( ! strcmp( picked, "Punch from edit" ) ) - { - if ( range_start() != range_end() ) - { - Loggable::block_start(); - - new Cursor_Region( range_start(), range_end() - range_start(), "Punch", NULL ); - reset_range(); - - Loggable::block_end(); - } - - redraw(); - } - else if ( ! strcmp( picked, "Playback from edit" ) ) - { - if ( range_start() != range_end() ) - { - Loggable::block_start(); - - if ( play_cursor_track->active_cursor() ) - { - play_cursor_track->active_cursor()->start( range_start() ); - play_cursor_track->active_cursor()->set_right( range_end() ); - } - else - { - new Cursor_Region( range_start(), range_end() - range_start(), "Playback", NULL ); - } - - reset_range(); - - Loggable::block_end(); - } - - redraw(); - } - else if ( ! strcmp( picked, "Redraw" ) ) - { - redraw(); - } - else if ( ! strcmp( picked, "Import source at mouse" ) ) - { - Fl::e_x = menu_event_x; - Fl::e_y = menu_event_y; - - Track *t = Timeline::event_inside(); - - if ( t ) - { - const char *name = fl_file_chooser( "Import source", "*", NULL ); - - if ( name ) - { - char *url; - asprintf( &url, "file:///%s\n", name ); - - Fl::e_x = menu_event_x; - Fl::e_y = menu_event_y; - - t->sequence()->handle_paste(url); - - free(url); - } - } - } - else - WARNING( "programming error: Unknown menu item" ); -} - -int -Timeline::ntracks ( void ) const -{ - return tracks->children(); -} - - -Timeline::~Timeline ( ) -{ - delete osc_thread; - osc_thread = 0; - delete osc; - osc = 0; -} - -Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W, H, L ) -{ - Loggable::snapshot_callback( &Timeline::snapshot, this ); - - edit_cursor_track = NULL; - punch_cursor_track = NULL; - play_cursor_track = NULL; - - _created_new_takes = 0; - osc_thread = 0; - _sample_rate = 44100; - - box( FL_FLAT_BOX ); - xoffset = 0; - _old_yposition = 0; - _old_xposition = 0; - -// range_start( range_end( 0 ) ); - - menu = new Fl_Menu_Button( 0, 0, 0, 0, "Timeline" ); - -/* menu->add( "Add Track", 0, 0, 0 ); */ - - int ruler_height = 0; - - menu->add( "Add audio track", 'a', 0, 0 ); - menu->add( "Tempo from edit (beat)", 't', 0, 0 ); - menu->add( "Tempo from edit (bar)", FL_CTRL + 't', 0, 0 ); - menu->add( "Playhead to mouse", 'p', 0, 0 ); - menu->add( "Edit start to mouse", '[', 0, 0 ); - menu->add( "Edit end to mouse", ']', 0, 0 ); - menu->add( "Playhead left beat", FL_SHIFT + FL_Left, 0, 0 ); - menu->add( "Playhead right beat", FL_SHIFT + FL_Right, 0, 0 ); - menu->add( "Playhead left bar", FL_CTRL + FL_SHIFT + FL_Left, 0, 0 ); - menu->add( "Playhead right bar", FL_CTRL + FL_SHIFT + FL_Right, 0, 0 ); - menu->add( "Swap edit start and playhead", FL_CTRL + FL_SHIFT + '[', 0, 0 ); - menu->add( "Swap edit end and playhead", FL_CTRL + FL_SHIFT + ']', 0, 0 ); - menu->add( "Edit start to playhead", FL_CTRL + '[', 0, 0 ); - menu->add( "Edit end to playhead", FL_CTRL + ']', 0, 0 ); - menu->add( "Punch from edit", FL_CTRL + FL_SHIFT + 'p', 0, 0 ); - menu->add( "Playback from edit", FL_CTRL + FL_SHIFT + 'l', 0, 0 ); - menu->add( "Import source at mouse", 0, 0, 0 ); - menu->add( "Redraw", FL_CTRL + 'l', 0, 0 ); - - menu_set_callback( const_cast(menu->menu()), &Timeline::menu_cb, (void*)this ); - - - { - Fl_Pack *o = new Fl_Pack( X, Y, W, 1, "rulers" ); - o->type( Fl_Pack::VERTICAL ); - - { - Tempo_Sequence *o = new Tempo_Sequence( 0, 0, 800, 18 ); - - o->color( FL_DARK1 ); - - /* o->label( "Tempo" ); */ - - tempo_track = o; - } - - { - Time_Sequence *o = new Time_Sequence( 0, 24, 800, 18 ); - - o->color( FL_DARK2 ); - - /* o->name( "Time" ); */ - - time_track = o; - } - - { - Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - - o->color( FL_DARK1 ); - - o->label( "Edit" ); - o->cursor_color( FL_YELLOW ); - - edit_cursor_track = o; - } - - { - Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - - o->color( FL_DARK2 ); - - o->label( "Punch" ); - o->cursor_color( FL_RED ); - - punch_cursor_track = o; - } - - { - Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 ); - - o->color( FL_DARK1 ); - - o->label( "Playback" ); - o->cursor_color( FL_GREEN ); - - play_cursor_track = o; - } - -/* { */ -/* Annotation_Sequence *o = new Annotation_Sequence( 0, 24, 800, 24 ); */ - -/* o->color( fl_gray_ramp( 'F' ) ); */ - -/* o->label( "Ruler" ); */ -/* o->align( FL_ALIGN_LEFT ); */ - -/* ruler_track = o; */ -/* } */ - - rulers = o; - o->end(); - - ruler_height = o->child( 0 )->h() * o->children(); - - DMESSAGE( "Ruler height: %i", ruler_height ); - - o->size( o->w(), ruler_height ); - } - - { - Fl_Tile *o = new Fl_Tile( X, rulers->y() + ruler_height, W, H - rulers->h() ); - o->box(FL_FLAT_BOX); - o->when( FL_WHEN_RELEASE ); - { - Fl_Group *o = new Fl_Group( X, rulers->y() + rulers->h(), W, ( H - rulers->h() ) - 50 ); - o->box(FL_FLAT_BOX); - o->clip_children(true); - o->resizable(NULL); - { - _fpp = 8; - Fl_Pack *o = new Fl_Pack( X, rulers->y() + rulers->h(), W, 1 ); - o->type( Fl_Pack::VERTICAL ); - o->spacing( 1 ); - - tracks = o; - o->end(); - /* Fl_Group::current()->resizable( o ); */ - } - - o->end(); - track_window = o; - } - { - Fl_Panzoomer *o = new Timeline_Panzoomer( X, - track_window->y() + track_window->h(), - W, - 50 ); - - o->zoom_range( 1, 20 ); - o->zoom( 8 ); - - o->box( FL_FLAT_BOX ); - o->color( FL_DARK1 ); - o->type( FL_HORIZONTAL ); - o->callback( cb_scroll, this ); - - panzoomer = o; - } - - /* this is used to define the sizing limits of the enclosing Fl_Tile */ - Fl_Box *spacebox = new Fl_Box( 0,0,1,1 ); - /* doesn't need to be visible */ - spacebox->hide(); - - o->end(); - o->resizable( spacebox ); - - spacebox->resize( X, rulers->y() + ( ( H - rulers->h() ) - 50 ), - W, 125 ); - - o->position( panzoomer->x(), panzoomer->y(), - panzoomer->x(), track_window->y() + track_window->h() ); - - tile = o; - resizable(o); - } - - /* rulers go above tracks... */ - add( rulers ); - - /* redraw(); */ - - end(); - - Fl::add_timeout( UPDATE_FREQ, update_cb, this ); -} - -void -Timeline::beats_per_minute ( nframes_t when, float bpm ) -{ - tempo_track->add( new Tempo_Point( when, bpm ) ); -} - -void -Timeline::time ( nframes_t when, int bpb, int note_type ) -{ - time_track->add( new Time_Point( when, bpb, note_type ) ); -} - -/************/ -/* Snapping */ -/************/ - -struct nearest_line_arg -{ - nframes_t original; - nframes_t closest; - bool bar; -}; - -const int snap_pixel = 10; - -static nframes_t -abs_diff ( nframes_t n1, nframes_t n2 ) -{ - return n1 > n2 ? n1 - n2 : n2 - n1; -} - -static void -nearest_line_snap_cb ( nframes_t frame, const BBT &bbt, void *arg ) -{ - nearest_line_arg *n = (nearest_line_arg *)arg; - - if ( n->bar && bbt.beat ) - return; - - if ( Timeline::snap_magnetic && - abs_diff( frame, n->original ) > timeline->x_to_ts( snap_pixel ) ) - return; - - if ( abs_diff( frame, n->original ) < abs_diff( n->original, n->closest ) ) - n->closest = frame; -} - -static void -nearest_line_cb ( nframes_t frame, const BBT &bbt, void *arg ) -{ - nearest_line_arg *n = (nearest_line_arg *)arg; - - if ( n->bar && bbt.beat ) - return; - - if ( abs_diff( frame, n->original ) < abs_diff( n->original, n->closest ) ) - n->closest = frame; -} - -static void -prev_next_line_cb ( nframes_t frame, const BBT &bbt, void *arg ) -{ - nearest_line_arg *n = (nearest_line_arg *)arg; - - if ( n->bar && bbt.beat ) - return; - - if ( abs_diff( frame, n->original ) < abs_diff( n->original, n->closest ) ) - n->closest = frame; -} - -/** Set the value pointed to by /frame/ to the frame number of the of - the nearest measure line to /when/. Returns true if the new value of - *frame is valid, false otherwise. */ -bool -Timeline::nearest_line ( nframes_t *frame, bool snap ) const -{ - if ( snap && ( snapping_on_hold || None == Timeline::snap_to ) ) - return false; - - nframes_t when = *frame; - - nearest_line_arg n = { when, JACK_MAX_FRAMES, snap && Timeline::Bars == Timeline::snap_to }; - - render_tempomap( when > x_to_ts( w() >> 1 ) ? when - x_to_ts( w() >> 1 ) : 0, - when + x_to_ts( w() >> 1 ), snap ? nearest_line_snap_cb : nearest_line_cb, &n ); - - if ( n.closest == JACK_MAX_FRAMES ) - return false; - else - { - *frame = n.closest; - return true; - } -} - -/** Set the value pointed to by /frame/ to the frame number of the of - the nearest measure line to *greater than* /when/. Returns true if - the new value of *frame is valid, false otherwise. */ -bool -Timeline::next_line ( nframes_t *frame, bool bar ) const -{ - const nframes_t when = *frame + 1; - - nearest_line_arg n = { when, JACK_MAX_FRAMES, bar }; - - const nframes_t window = sample_rate() * 60; - nframes_t length = window; - - if ( when > JACK_MAX_FRAMES - length ) - length = JACK_MAX_FRAMES - when; - - render_tempomap( when, length, prev_next_line_cb, &n ); - - *frame = n.closest; - - return true; -} - -/** Set the value pointed to by /frame/ to the frame number of the of - the nearest measure line to *less than* /when/. Returns true if - the new value of *frame is valid, false otherwise. */ -bool -Timeline::prev_line ( nframes_t *frame, bool bar ) const -{ - if ( ! *frame ) - return false; - - const nframes_t when = *frame - 1; - - nearest_line_arg n = { when, 0, bar }; - - const nframes_t window = sample_rate() * 60; - nframes_t start = 0; - nframes_t length = when; - - if ( when > window ) - { - start = when - window; - length = window; - } - - render_tempomap( start, length, prev_next_line_cb, &n ); - - *frame = n.closest; - - return true; -} - - - -/** given screen pixel coordinate /x/ return frame offset into - * timeline, taking into account the current scroll position, widget - * layout, etc. */ -nframes_t -Timeline::x_to_offset ( int x ) const -{ - int d = x - Track::width(); - - int64_t r; - - if ( d < 0 ) - r = (int64_t)xoffset - x_to_ts( 0 - d ); - else - r = (int64_t)xoffset + x_to_ts( d ); - - if ( r > JACK_MAX_FRAMES ) - return JACK_MAX_FRAMES; - else if ( r < 0 ) - return 0; - else - return r; -} - -int -Timeline::offset_to_x ( nframes_t frame ) const -{ - return ts_to_x( frame - xoffset ) + Track::width(); -} - -/** draws a single measure line */ -void -Timeline::draw_measure_cb ( nframes_t frame, const BBT &bbt, void *v ) -{ - Timeline *o = (Timeline*)v; - - Fl_Color c = FL_LIGHT3; - - if ( o->panzoomer->zoom() >= 15 ) - return; - - if ( bbt.beat ) - { - if ( o->panzoomer->zoom() > 12 ) - return; - else - c = FL_DARK1; - } - - fl_color( fl_color_add_alpha( c, 64 ) ); - - const int x = timeline->ts_to_x( frame - timeline->xoffset ) + Track::width(); - - fl_line( x, 0, x, 2000 ); -} - -/* FIXME: wrong place for this */ -const float ticks_per_beat = 1920.0; - -/** re-render the unified tempomap based on the current contents of the Time and Tempo sequences */ -void -Timeline::update_tempomap ( void ) -{ - /* FIXME: we need some type of locking! */ - _tempomap.clear(); - - for ( list ::const_iterator i = time_track->_widgets.begin(); - i != time_track->_widgets.end(); ++i ) - _tempomap.push_back( *i ); - - for ( list ::const_iterator i = tempo_track->_widgets.begin(); - i != tempo_track->_widgets.end(); ++i ) - _tempomap.push_back( *i ); - - _tempomap.sort( Sequence_Widget::sort_func ); -} - -/** return a stucture containing the BBT info which applies at /frame/ */ -position_info -Timeline::solve_tempomap ( nframes_t frame ) const -{ - return render_tempomap( frame, 0, 0, 0 ); -} - -/* THREAD: UI and RT */ -/** draw appropriate measure lines inside the given bounding box */ -position_info -Timeline::render_tempomap( nframes_t start, nframes_t length, measure_line_callback * cb, void *arg ) const -{ - const nframes_t end = start + length; - - position_info pos; - memset( &pos, 0, sizeof( pos ) ); - - BBT &bbt = pos.bbt; - - /* default values */ - pos.beat_type = 4; - pos.beats_per_bar = 4; - pos.tempo = 120.0; - - const nframes_t samples_per_minute = sample_rate() * 60; - - float bpm = 120.0f; - - time_sig sig; - - sig.beats_per_bar = 4; - sig.beat_type = 4; - - nframes_t f = 0; - nframes_t next = 0; - - nframes_t frames_per_beat = samples_per_minute / bpm; - - if ( ! _tempomap.size() ) - return pos; - - for ( list ::const_iterator i = _tempomap.begin(); - i != _tempomap.end(); ++i ) - { - - if ( ! strcmp( (*i)->class_name(), "Tempo_Point" ) ) - { - const Tempo_Point *p = (Tempo_Point*)(*i); - - bpm = p->tempo(); - frames_per_beat = samples_per_minute / bpm; - } - else - { - const Time_Point *p = (Time_Point*)(*i); - - sig = p->time(); - - /* Time point resets beat */ - bbt.beat = 0; - } - - { - list ::const_iterator n = i; - ++n; - if ( n == _tempomap.end() ) - next = end; - else -// next = min( (*n)->start(), end ); - /* points may not always be aligned with beat boundaries, so we must align here */ - next = (*n)->start() - ( ( (*n)->start() - (*i)->start() ) % frames_per_beat ); - } - - for ( ; f < next; ++bbt.beat, f += frames_per_beat ) - { - - if ( bbt.beat == sig.beats_per_bar ) - { - bbt.beat = 0; - ++bbt.bar; - } - - if ( f >= start ) - { - /* in the zone */ - if ( cb ) - cb( f, bbt, arg ); - } - - /* ugliness to avoid failing out at -1 */ - if ( end >= frames_per_beat ) - { - if ( f >= end - frames_per_beat ) - goto done; - } - else if ( f + frames_per_beat >= end ) - goto done; - } - } - -done: - - pos.frame = f; - pos.tempo = bpm; - pos.beats_per_bar = sig.beats_per_bar; - pos.beat_type = sig.beat_type; - - assert( f <= end ); - - assert( end - f <= frames_per_beat ); - - /* FIXME: this this right? */ - - const double frames_per_tick = frames_per_beat / ticks_per_beat; - bbt.tick = ( end - f ) / frames_per_tick; - - return pos; -} - -/** maybe draw appropriate measure lines in rectangle defined by X, Y, W, and H, using color /color/ as a base */ -void -Timeline::draw_measure_lines ( int X, int Y, int W, int H ) -{ - if ( ! draw_with_measure_lines ) - return; - - fl_line_style( FL_SOLID, 0 ); - - const nframes_t start = x_to_offset( X ); - const nframes_t length = x_to_ts( W ); - - fl_push_clip( X, Y, W, H ); - - render_tempomap( start, length, draw_measure_cb, this ); - - fl_pop_clip(); -} - -void -Timeline::draw_clip_rulers ( void * v, int X, int Y, int W, int H ) -{ - Timeline *tl = (Timeline *)v; - - fl_push_clip( X, Y, W, H ); - - tl->draw_box(); - - tl->draw_child( *tl->rulers ); - - fl_pop_clip(); -} - -void -Timeline::draw_clip_tracks ( void * v, int X, int Y, int W, int H ) -{ - Timeline *tl = (Timeline *)v; - - fl_push_clip( X, Y, W, H ); - - tl->draw_box(); - - fl_damage_t pzd = tl->panzoomer->damage(); - - tl->draw_child( *tl->tile ); - - tl->panzoomer->damage( pzd ); - - fl_pop_clip(); -} - -/** handle resize event */ -void -Timeline::resize ( int X, int Y, int W, int H ) -{ - int old_panzoomer_h = panzoomer->h(); - - BASE::resize( X, Y, W, H ); - - tile->resizable()->resize( X, - tile->y() + tile->h() - 150, - W, 125 ); - - panzoomer->resize( X, - tile->y() + tile->h() - old_panzoomer_h, - W, - old_panzoomer_h ); - - track_window->resize( X, - tile->y(), - W, - tile->h() - panzoomer->h()); - - tracks->resize( tracks->x(), tracks->y(), W, tracks->h() ); - - /* /\* rulers->resize( X, *\/ */ - /* /\* rulers->y(), *\/ */ - /* /\* W, *\/ */ - /* /\* rulers->h() ); *\/ */ - - /* tile->redraw(); */ -} - - -void -Timeline::add_cursor ( Cursor_Region *o ) -{ - if ( !strcmp( o->type(), "Edit" ) ) - { - DMESSAGE( "Adding cursor to edit track" ); - edit_cursor_track->add( o ); - } - else if ( !strcmp( o->type(), "Punch" ) ) - { - DMESSAGE( "Adding cursor to punch track" ); - punch_cursor_track->add( o ); - } - else if ( !strcmp( o->type(), "Playback" ) ) - { - DMESSAGE( "Adding cursor to punch track" ); - play_cursor_track->add( o ); - } - -} - -void -Timeline::add_cursor ( Cursor_Point *o ) -{ - if ( !strcmp( o->type(), "Edit" ) ) - edit_cursor_track->add( o ); - else if ( !strcmp( o->type(), "Punch" ) ) - punch_cursor_track->add( o ); -} - -void -Timeline::draw_cursors ( Cursor_Sequence *o ) const -{ - fl_push_clip( tracks->x() + Track::width(), rulers->y() + rulers->h(), tracks->w() - Track::width(), h() - rulers->h() - panzoomer->h() ); - - if ( o && o->_widgets.size() > 0 ) - { - for ( std::list::const_iterator i = o->_widgets.begin(); - i != o->_widgets.end(); - i++ ) - { - if ( Timeline::draw_with_cursor_overlay ) - { - fl_color( fl_color_add_alpha( (*i)->box_color(), 25 ) ); - - fl_rectf( (*i)->line_x(), tracks->y(), (*i)->abs_w(), tracks->h() ); - } - else - { - fl_color( fl_color_add_alpha( (*i)->box_color(), 127 )); - - fl_line( (*i)->line_x(), tracks->y(), (*i)->line_x(), tracks->y() + tracks->h() ); - - fl_line( (*i)->line_x() + (*i)->abs_w(), tracks->y(), (*i)->line_x() + (*i)->abs_w(), tracks->y() + tracks->h() ); - } - } - } - - fl_pop_clip(); -} - -/** draw ancillary cursors (not necessarily in the overlay plane) */ -void -Timeline::draw_cursors ( void ) const -{ - draw_cursors( edit_cursor_track ); - - if ( transport->punch_enabled() ) - draw_cursors( punch_cursor_track ); -} - - -void -Timeline::draw ( void ) -{ - /* Any code that might affect the structures used for drawing from - * another thread must use Fl::lock()/unlock()! */ - THREAD_ASSERT( UI ); - -// rdlock(); - - int X, Y, W, H; - - int bdx = 0; - int bdw = 0; - - X = tracks->x() + bdx + 1; - Y = tracks->y(); - W = tracks->w() - bdw - 1; - H = tracks->h(); - - adjust_panzoomer(); - - int dx = ts_to_x( _old_xposition ) - ts_to_x( xoffset ); - int dy = _old_yposition - (int)panzoomer->y_value(); - - int c = damage(); - -// c = FL_DAMAGE_ALL; - - if ( c & FL_DAMAGE_SCROLL ) - { - { - /* draw_child( *rulers ); */ - - Y = track_window->y(); - H = track_window->h(); - - - if ( dx ) - /* when scrolling horizontally, scroll rulers */ - fl_scroll( rulers->x() + Track::width(), - rulers->y(), - rulers->w(), - rulers->h(), dx, 0, draw_clip_rulers, this ); - - if ( dy ) - /* when scrolling vertically, also scroll track headers */ - fl_scroll( - X, - Y, - Track::width(), - H, 0, dy, draw_clip_tracks, this ); - - /* scroll sequences */ - fl_scroll( X + Track::width(), - Y, - W - Track::width(), - H, dx, dy, draw_clip_tracks, this ); - } - } - -// panzoomer->redraw(); - - if ( c & FL_DAMAGE_ALL ) - { - DMESSAGE( "complete redraw" ); - - draw_box( box(), BX, BY, w(), h(), color() ); - - draw_child( *rulers ); - - fl_push_clip( tile->x(), - tile->y(), - tile->w(), - tile->h() ); - - draw_child(*tile); - - fl_pop_clip(); - - redraw_overlay(); - - goto done; - } - - if ( c & FL_DAMAGE_CHILD ) - { - update_child(*rulers); - - fl_push_clip( tile->x(), - tile->y(), - tile->w(), - tile->h() ); - - /* redraw the panzoomer preview whenever tracks change */ - /* if ( tracks->damage() ) */ - /* panzoomer->redraw(); */ - - update_child(*tile); - - fl_pop_clip(); - - redraw_overlay(); - } - -done: - -// unlock(); - - /* panzoomer->redraw(); */ -// update_child( *panzoomer ); - - _old_xposition = xoffset; - _old_yposition = panzoomer->y_value(); -} - -void -Timeline::damage_sequence ( void ) -{ - panzoomer->redraw(); -} - -/** draw a single cursor line at /frame/ with color /color/ using symbol routine /symbol/ for the cap */ -void -Timeline::draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const -{ -// int x = ( ts_to_x( frame ) - ts_to_x( xoffset ) ) + tracks->x() + Track::width(); - - if ( frame < xoffset ) - return; - - const int x = ts_to_x( frame - xoffset ) + tracks->x() + Track::width(); - - if ( x > tracks->x() + tracks->w() ) - return; - - const int y = rulers->y() + rulers->h(); - const int h = this->h() - rulers->h() - panzoomer->h(); - - fl_push_clip( tracks->x() + Track::width(), y, tracks->w(), h ); - - fl_line_style( FL_SOLID, 0 ); - fl_color( color ); - fl_line( x, y, x, y + h ); - - fl_push_matrix(); - - fl_translate( x, y ); - fl_scale( 8, 4 ); - - symbol( color ); - - fl_pop_matrix(); - - fl_pop_clip(); -} - -/** set /in/ and /out/ to start and end of next punch region from /frame/ */ -bool -Timeline::next_punch ( nframes_t frame, nframes_t *in, nframes_t *out ) const -{ - if ( !transport->punch_enabled() ) - return false; - - const Sequence_Widget *w = punch_cursor_track->next( frame ); - - if ( w && w->start() >= frame ) - { - *in = w->start(); - *out = w->start() + w->length(); - - return true; - } - - return false; -} - -void -Timeline::draw_playhead ( void ) -{ - draw_cursor( transport->frame, FL_RED, draw_full_arrow_symbol ); -// draw_cursor( length(), FL_BLACK, draw_full_arrow_symbol ); -} - -void -Timeline::redraw_playhead ( void ) -{ -// static nframes_t last_playhead = -1; - static int last_playhead_x = -1; - - if ( transport->rolling ) - { - if ( play_cursor_track->active_cursor() ) - { - if ( transport->loop_enabled() ) - { - if ( transport->frame > playback_end() ) - { - if ( ! seek_pending() ) - { - if ( transport->recording ) - { - stop(); - transport->locate( playback_home() ); - record(); - } - else - { - transport->locate( playback_home() ); - } - } - } - } - else - if ( transport->frame > playback_end() ) - transport->stop(); - } - } - - int playhead_x = ts_to_x( transport->frame ); - - if ( last_playhead_x != playhead_x ) - { - redraw_overlay(); -// last_playhead = transport->frame; - last_playhead_x = playhead_x; - - if ( follow_playhead ) - { - if ( center_playhead && active() ) - xposition( max( 0, playhead_x - ( ( tracks->w() - Track::width() ) >> 1 ) ) ); - else if ( playhead_x > ts_to_x( xoffset ) + ( tracks->w() - Track::width() ) ) - xposition( playhead_x ); - adjust_panzoomer(); - } - } -} - -/** called so many times a second to redraw the playhead etc. */ -void -Timeline::update_cb ( void *arg ) -{ - Fl::repeat_timeout( UPDATE_FREQ, update_cb, arg ); - - Timeline *tl = (Timeline *)arg; - - tl->redraw_playhead(); -} - -/** draw cursors in overlay plane */ -void -Timeline::draw_overlay ( void ) -{ - draw_playhead(); - - draw_cursors(); - - if ( ! ( _selection.w && _selection.h ) ) - return; - - fl_push_clip( tracks->x() + Track::width(), rulers->y() + rulers->h(), tracks->w() - Track::width(), h() - rulers->h() - panzoomer->h() ); - - const Rectangle &r = _selection; - - fl_color( FL_MAGENTA ); - fl_line_style( FL_SOLID, 0 ); - fl_rect( r.x, r.y, r.w, r.h ); - - fl_pop_clip(); -} - -/** select sequence widgets within rectangle /r/ */ -void -Timeline::select ( const Rectangle &r ) -{ - const int Y = r.y; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( ! ( t->y() > Y + r.h || t->y() + t->h() < Y ) ) - t->select( r.x, r.y, r.w, r.h, true, true ); - } -} - -/** delete all selected sequence widgets */ -void -Timeline::delete_selected ( void ) -{ - Sequence_Widget::delete_selected(); -} - -/** clear the selection of seqeunce widgets */ -void -Timeline::select_none ( void ) -{ - Sequence_Widget::select_none(); -} - -int -Timeline::nselected ( void ) const -{ - return Sequence_Widget::nselected(); -} - -/** An unfortunate necessity for implementing our own DND aside from - * the (bogus) native FLTK system */ -Track * -Timeline::track_under ( int Y ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( ! ( t->y() > Y || t->y() + t->h() < Y ) ) - return t; - } - - return NULL; -} - -#include "FL/event_name.H" -#include "FL/test_press.H" - -/** a bit of a hack to keep FLTK's focus navigation stuff from - * stealing the arrow keys from us */ -int -Timeline::handle_scroll ( int m ) -{ - if ( m == FL_KEYBOARD && - Fl::event_key() != FL_Home && - Fl::event_key() != FL_End ) - return menu->test_shortcut() || panzoomer->handle( m ); - else - return 0; -} - -Track * -Timeline::event_inside ( void ) -{ - for ( int i = tracks->children(); i--; ) - if ( Fl::event_inside( tracks->child(i) ) ) - return (Track*)tracks->child(i); - - return NULL; -} - -int -Timeline::handle ( int m ) -{ - static Drag *drag = NULL; - static bool range = false; - -/* if ( m != FL_NO_EVENT ) */ -/* DMESSAGE( "%s", event_name( m ) ); */ - -/* int r = BASE::handle( m ); */ - - switch ( m ) - { - case FL_ENTER: - return 1; - case FL_LEAVE: - return 1; - case FL_KEYDOWN: - if ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) - /* we don't want any keys with modifiers... */ - return 0; - - if ( Fl::event_key() == 'r' ) - { - range = true; - return 1; - } - else if ( Fl::event_key() == 's' ) - { - snapping_on_hold = true; - return 1; - } - return 0; - case FL_KEYUP: - if ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) - /* we don't want any keys with modifiers... */ - return 0; - - if ( Fl::event_key() == 'r' ) - { - range = false; - return 1; - } - else if ( Fl::event_key() == 's' ) - { - snapping_on_hold = false; - return 1; - } - return 0; -// case FL_KEYBOARD: - case FL_SHORTCUT: - { - if ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) - /* we don't want any keys with modifiers... */ - return 0; - - switch ( Fl::event_key() ) - { - case FL_Delete: - case FL_Home: - case FL_End: - /* keep scrollbar from eating these. */ - return 0; - default: - return BASE::handle( m ); - } - - return 0; - } - default: - { - int r = BASE::handle( m ); - - if ( m != FL_RELEASE && r ) - return r; - - const int X = Fl::event_x(); - const int Y = Fl::event_y(); - - switch ( m ) - { - case FL_PUSH: - { - if ( - Fl::event_x() >= Track::width() && - ( test_press( FL_BUTTON1 ) || test_press( FL_BUTTON1 + FL_CTRL ) )) - { - assert( ! drag ); - - drag = new Drag( X, Y ); - _selection.x = X; - _selection.y = Y; - - if ( ! Fl::event_ctrl() ) - select_none(); - - return 1; - } - else if ( test_press( FL_BUTTON3 ) ) - { - { - menu_event_x = X; - menu_event_y = Y; - - Track *t = Timeline::event_inside(); - - Fl_Menu_Item *mi = (Fl_Menu_Item*)menu->find_item("Import source at mouse"); - - if ( t ) - mi->activate(); - else - mi->deactivate(); - } - - menu_popup( menu ); - - return 1; - } - } - - return 0; - - case FL_DRAG: - { - int ox = X - drag->x; - int oy = Y - drag->y; - - if ( ox < 0 ) - _selection.x = X; - if ( oy < 0 ) - _selection.y = Y; - - _selection.w = abs( ox ); - _selection.h = abs( oy ); - - if ( range ) - { - range_start( x_to_offset( _selection.x ) ); - range_end( x_to_offset( _selection.x + _selection.w ) ); - redraw(); - } - - redraw_overlay(); - return 1; - - break; - } - case FL_RELEASE: - { - delete drag; - drag = NULL; - - if ( range ) - { - range_start( x_to_offset( _selection.x ) ); - range_end( x_to_offset( _selection.x + _selection.w ) ); - redraw(); - } - else - select( _selection ); - - _selection.x = _selection.y =_selection.w = _selection.h = 0; - - redraw_overlay(); - return 1; - } - default: - return 0; - break; - } - - return 0; - } - } -} - -/** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */ -Track * -Timeline::track_by_name ( const char *name ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( name && t->name() && ! strcmp( name, t->name() ) ) - return t; - } - - return NULL; -} - -/** return a malloc'd string representing a unique name for a new track */ -char * -Timeline::get_unique_track_name ( const char *name ) -{ - char pat[256]; - - strcpy( pat, name ); - - for ( int i = 1; track_by_name( pat ); ++i ) - snprintf( pat, sizeof( pat ), "%s.%d", name, i ); - - return strdup( pat ); -} - -/**********/ -/* Public */ -/**********/ - -/** return the current length of the timeline, which is arrived at by - * calculating the end frame of the rightmost audio region on an - * active audio sequence. Control_Points, etc. do not factor into this - * calcaulation. */ -nframes_t -Timeline::length ( void ) const -{ - nframes_t l = 0; - - for ( int i = tracks->children(); i--; ) - { - Sequence *t = ((Track*)tracks->child( i ))->sequence(); - - if ( t ) - l = max( l, ((Track*)tracks->child( i ))->sequence()->length() ); - } - - return l; -} - -/** set horizontal scroll postion to absolute pixel coordinate /X/ */ -void -Timeline::xposition ( int X ) -{ - xoffset = x_to_ts( X ); - - long dx = ts_to_x( _old_xposition ) - ts_to_x( xoffset ); - - if ( dx ) - damage( FL_DAMAGE_SCROLL ); -} - -/** zoom in by one zoom step */ -void -Timeline::zoom_in ( void ) -{ - panzoomer->zoom_in(); -} - -/** zoom out by one zoom step */ -void -Timeline::zoom_out ( void ) -{ - panzoomer->zoom_out(); -} - -/** zoom the display to show /secs/ seconds per screen */ -void -Timeline::zoom ( float secs ) -{ - const int sw = tracks->w() - Track::width(); - - int fpp = (int)((secs * sample_rate()) / sw); - - int p = 0; - while ( 1 << p < fpp ) p++; - - panzoomer->zoom( p ); - - redraw(); -} - -/** fit the zoom to the current length of the timeline (subject to nearest power of two) */ -void -Timeline::zoom_fit ( void ) -{ - xposition( 0 ); - - if ( length() ) - zoom( length() / (float)sample_rate() ); - else - zoom( 60 ); -} - -/** add /track/ to the timeline */ -void -Timeline::add_track ( Track *track ) -{ - DMESSAGE( "added new track to the timeline" ); - - tracks->add( track ); - - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ - redraw(); - -} - -void -Timeline::insert_track ( Track *track, Track *before ) -{ - tracks->insert( *track, before ); - - tracks->redraw(); -} - -void -Timeline::insert_track ( Track *track, int n ) -{ - if ( n > tracks->children() || n < 0 ) - return; - - tracks->insert( *track, n ); - - tracks->redraw(); - - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ -// redraw(); -} - -static -bool -compare_tracks ( Track *a, Track *b ) -{ - return *a < *b; -} - -void -Timeline::apply_track_order ( void ) -{ - /* wrlock(); */ - - std::list tl; - - for ( int i = 0; i < tracks->children(); i++ ) - tl.push_back( (Track*)tracks->child( i ) ); - - tl.sort(compare_tracks); - - Fl_Widget **a = const_cast(tracks->array()); - - int j = 0; - for ( std::list::const_iterator i = tl.begin(); - i != tl.end(); - i++, j++ ) - a[j] = *i; - - update_track_order(); - - /* unlock(); */ -} - -void -Timeline::update_track_order ( void ) -{ - for ( int i = 0; i < tracks->children(); i++ ) - ((Track*)tracks->child( i ))->row( i ); -} - -int -Timeline::find_track ( const Track *track ) const -{ - return tracks->find( *track ); -} - - -/** remove /track/ from the timeline */ -void -Timeline::remove_track ( Track *track ) -{ - DMESSAGE( "removed track from the timeline" ); - - /* FIXME: what to do about track contents? */ - tracks->remove( track ); - - /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ - redraw(); -} - -/************/ -/* Commands */ -/************/ - -void -Timeline::command_move_track_up ( Track *track ) -{ - track_lock.wrlock(); - insert_track( track, find_track( track ) - 1 ); - track_lock.unlock(); -} - -void -Timeline::command_move_track_down ( Track *track ) -{ - track_lock.wrlock(); - insert_track( track, find_track( track ) + 2 ); - track_lock.unlock(); -} - -void -Timeline::command_remove_track ( Track *track ) -{ - track_lock.wrlock(); - remove_track(track); - track_lock.unlock(); -} - -void -Timeline::command_quit ( void ) -{ - track_lock.wrlock(); - - Project::close(); - - track_lock.unlock(); - - command_save(); - - while ( Fl::first_window() ) Fl::first_window()->hide(); -} - -void -Timeline::command_undo ( void ) -{ - /* FIXME: sequence lock too? */ - track_lock.wrlock(); - Project::undo(); - track_lock.unlock(); -} - -bool -Timeline::command_load ( const char *name, const char *display_name ) -{ - if ( ! name ) - return false; - - track_lock.wrlock(); - int r = Project::open( name ); - track_lock.unlock(); - - if ( r < 0 ) - { - const char *s = Project::errstr( r ); - - fl_alert( "Could not open project \"%s\":\n\n\t%s", name, s ); - - return false; - } - - if ( display_name ) - Project::set_name ( display_name ); - - apply_track_order(); - - return true; -} - -bool -Timeline::command_save ( ) -{ - tle->save_options(); - - return true; -} - -bool -Timeline::command_new ( const char *name, const char *display_name ) -{ - bool b = Project::create( name, NULL ); - - Project::set_name ( display_name ); - - /* FIXME: there's other stuff that needs to be done here! */ - /* tle->update_menu(); */ - - /* tle->main_window->redraw(); */ - - return b; -} - -const char * -Timeline::session_manager_name ( void ) -{ - return nsm_get_session_manager_name( nsm ); -} - - -/*******/ -/* OSC */ -/*******/ - -int -Timeline::init_osc ( const char *osc_port ) -{ - osc = new OSC::Endpoint(); - - if ( int r = osc->init( LO_UDP, osc_port ) ) - return r; - - osc->owner = this; - - char *url = osc->url(); - printf( "OSC=%s\n", url ); - free(url); - - osc->add_method( "/non/hello", "ssss", &Timeline::osc_non_hello, osc, "" ); - -// osc->start(); - - if ( ! osc_thread ) - { - osc_thread = new OSC_Thread(); - - osc_thread->start(); - } - - return 0; -} - -int -Timeline::osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ) -{ - THREAD_ASSERT( OSC ); - - timeline->handle_hello(msg); - return 0; -} - -void -Timeline::handle_hello ( lo_message msg ) -{ - int argc = lo_message_get_argc( msg ); - lo_arg **argv = lo_message_get_argv( msg ); - - if ( argc >= 4 ) - { - const char *url = &argv[0]->s; - const char *name = &argv[1]->s; - const char *version = &argv[2]->s; - const char *id = &argv[3]->s; - - MESSAGE( "Got hello from NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id ); - - osc->handle_hello( &argv[3]->s, &argv[0]->s ); - } -} - -void -Timeline::say_hello ( void ) -{ - if ( nsm_is_active( nsm ) ) - { - lo_message m = lo_message_new(); - - lo_message_add( m, "sssss", - "/non/hello", - osc->url(), - APP_NAME, - VERSION, - instance_name ); - - nsm_send_broadcast( nsm, m ); - } -} - -void -Timeline::connect_osc ( void ) -{ - /* reconnect OSC signals */ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->connect_osc(); - } -} -void -Timeline::update_osc_connection_state ( void ) -{ - /* reconnect OSC signals */ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->update_osc_connection_state(); - } -} - -/* runs in the OSC thread... */ -void -Timeline::process_osc ( void ) -{ - THREAD_ASSERT( OSC ); - - sequence_lock.rdlock(); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->process_osc(); - } - - sequence_lock.unlock(); -} - diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H deleted file mode 100644 index 022c3af..0000000 --- a/timeline/src/Timeline.H +++ /dev/null @@ -1,320 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - - -/* FIXME: this class needs a lot of cleaning up. Too many public - * members etc. */ - -/* #include "Audio_File.H" // just for nframes_t */ - -#include "types.h" - -#include -#include -#include - -#include "OSC_Thread.H" - -class Fl_Scroll; -class Fl_Pack; -class Fl_Scrollbar; -class Fl_Widget; - -class Fl_Menu_Button; -class Fl_Menu_; - -class Timeline; -extern Timeline *timeline; - -struct BBT; -class Tempo_Sequence; -class Time_Sequence; -class Annotation_Sequence; -class Cursor_Sequence; -class Track; -class Sequence; -class Sequence_Widget; -class Cursor_Region; -class Cursor_Point; -class Fl_Panzoomer; -class Fl_Tile; - -#include "RWLock.H" -#include - -namespace OSC { class Endpoint; } - -#include - -struct position_info; - -struct Rectangle -{ - int x; - int y; - int w; - int h; - - Rectangle ( ) : x( 0 ), y( 0 ), w( 0 ), h( 0 ) {} - Rectangle ( int X, int Y, int W, int H ) : x( X ), y( Y ), w( W ), h( H ) {} -}; - -class Timeline : public Fl_Group -{ - class Timeline_Panzoomer; - - static void draw_clip_rulers ( void * v, int X, int Y, int W, int H ); - static void draw_clip_tracks ( void * v, int X, int Y, int W, int H ); - - nframes_t _old_xposition; - int _old_yposition; - - Rectangle _selection; - - Fl_Group *track_window; - Fl_Pack *tracks; - Fl_Pack *rulers; - Fl_Tile *tile; - Fl_Panzoomer *panzoomer; - - void adjust_panzoomer ( void ); - static void cb_scroll ( Fl_Widget *w, void *v ); - void cb_scroll ( Fl_Widget *w ); - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( Fl_Menu_ *m ); - void fix_range ( void ); - - static void draw_measure_cb ( nframes_t frame, const BBT &bbt, void * ); - - int _fpp; /* frames per pixel, power of two */ - -// nframes_t p1, p2; /* cursors */ - nframes_t _playhead; - - /* not permitted */ - Timeline ( const Timeline &rhs ); - Timeline & operator = ( const Timeline &rhs ); - - std::list _tempomap; - - static void handle_peer_scan_complete ( void * v ); - - void update_track_order ( void ); - void apply_track_order ( void ); - void insert_track ( Track *track, int n ); - - -public: - - RWLock track_lock; /* tracks/sequences */ - RWLock sequence_lock; /* sequence contents */ - - void redraw_overlay ( void ); - - void insert_track ( Track *track, Track *before ); - Track * event_inside ( void ); - - /* called when widgets are moved etc */ - void damage_sequence ( void ); - - OSC::Endpoint *osc; - OSC_Thread *osc_thread; - - void process_osc ( void ); -#undef Bars -#undef Beats -#undef None - - enum snap_e { - Bars, - Beats, - None - }; - - /* configuration values */ - static bool draw_with_measure_lines; - static bool draw_with_cursor_overlay; - static snap_e snap_to; - static bool snapping_on_hold; - static bool snap_magnetic; - static bool follow_playhead; - static bool center_playhead; - static bool playback_latency_compensation; - - Tempo_Sequence *tempo_track; - Time_Sequence *time_track; - Annotation_Sequence *ruler_track; - Cursor_Sequence *edit_cursor_track; - Cursor_Sequence *punch_cursor_track; - Cursor_Sequence *play_cursor_track; - - Fl_Menu_Button *menu; - - bool _created_new_takes; - - nframes_t xoffset; - - nframes_t _sample_rate; - - Timeline ( int X, int Y, int W, int H, const char *L=0 ); - - virtual ~Timeline ( ); - - void update_tempomap ( void ); - - const char *session_manager_name ( void ); - - - nframes_t fpp ( void ) const { return 1 << _fpp; } - void range ( nframes_t start, nframes_t length ); - - nframes_t range_start ( void ) const; - nframes_t range_end ( void ) const; - void range_start ( nframes_t n ); - void range_end ( nframes_t n ); - void reset_range ( void ); - nframes_t playback_home ( void ) const; - nframes_t playback_end ( void ) const; - -// nframes_t playhead ( void ) const { return transport->frame; } - nframes_t length ( void ) const; - void sample_rate ( nframes_t r ) { _sample_rate = r; } - nframes_t sample_rate ( void ) const { return _sample_rate; } - int ts_to_x( nframes_t ts ) const { return ts >> _fpp; } - nframes_t x_to_ts ( int x ) const { return (nframes_t)x << _fpp; } - nframes_t x_to_offset ( int x ) const; - int offset_to_x ( nframes_t frame ) const; - - float beats_per_minute ( nframes_t when ) const; - int beats_per_bar ( nframes_t when ) const; - void beats_per_minute ( nframes_t when, float bpm ); - void time ( nframes_t when, int bpb, int beat_type ); - bool nearest_line ( nframes_t *f, bool snap=true ) const; - bool next_line ( nframes_t *f, bool bar=false ) const; - bool prev_line ( nframes_t *f, bool bar=false ) const; - - typedef void (measure_line_callback)( nframes_t frame, const BBT & bbt, void *arg ); - - position_info solve_tempomap ( nframes_t when ) const; - void draw_measure_lines ( int X, int Y, int W, int H ); - void draw_measure_BBT ( int X, int Y, int W, int H ); - position_info render_tempomap ( nframes_t start, nframes_t length, measure_line_callback *cb, void *arg ) const; - - void xposition ( int X ); - void draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const; - void draw_cursors ( Cursor_Sequence *o ) const; - void draw_cursors ( void ) const; - void draw_playhead ( void ); - void redraw_playhead ( void ); - void resize ( int X, int Y, int W, int H ); - - void draw ( void ); - void draw_overlay ( void ); - int handle_scroll ( int m ); - int handle ( int m ); - static void update_cb ( void *arg ); - - void select( const Rectangle &r ); - Track * track_under ( int Y ); - - int nselected ( void ) const; - void delete_selected ( void ); - void select_none ( void ); - - void add_track ( Track *track ); - void remove_track ( Track *track ); - void command_remove_track ( Track *track ); - - void command_move_track_up ( Track *track ); - void command_move_track_down ( Track *track ); - void command_undo ( void ); - - int find_track ( const Track * track ) const; - - int ntracks ( void ) const; - - void zoom ( float secs ); - void zoom_in ( void ); - void zoom_out ( void ); - void zoom_fit ( void ); - - bool next_punch ( nframes_t frame, nframes_t *in, nframes_t *out ) const; - - /* Engine */ - int total_input_buffer_percent ( void ); - int total_output_buffer_percent ( void ); - - int total_playback_xruns ( void ); - int total_capture_xruns ( void ); - - bool record ( void ); - void stop ( void ); - void punch_out ( nframes_t frame ); - - void wait_for_buffers ( void ); - bool seek_pending ( void ); - - bool command_load ( const char *name, const char *display_name ); - bool command_new ( const char *name, const char *display_name ); - bool command_save ( void ); - void command_quit ( void ); - - /* OSC */ - - void connect_osc ( void ); - - void update_osc_connection_state ( void ); - - void say_hello ( void ); - - static void check_osc ( void * v ); - - int init_osc ( const char *osc_port ); - - static int osc_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - static int osc_non_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); - - - void handle_hello ( lo_message msg ); - - void add_cursor ( Cursor_Region *o ); - void add_cursor ( Cursor_Point *o ); - - char * get_unique_track_name ( const char *name ); - Track * track_by_name ( const char *name ); - -private: - - void add_take_for_armed_tracks(); - void resize_rulers ( void ); - - static void snapshot ( void *v ) { ((Timeline*)v)->snapshot(); } - void snapshot ( void ); - - friend class Engine; // FIXME: only Engine::process() needs to be friended.x - - - /* Engine */ - void resize_buffers ( nframes_t nframes ); - nframes_t process_input ( nframes_t nframes ); - nframes_t process_output ( nframes_t nframes ); - void seek ( nframes_t frame ); -}; diff --git a/timeline/src/Track.C b/timeline/src/Track.C deleted file mode 100644 index 0e0ecf6..0000000 --- a/timeline/src/Track.C +++ /dev/null @@ -1,1297 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* A Track is a container for various sequences; the sequence, the - * takes (inactive sequences), annotation sequences, control - * sequences */ -/* TODO: split into Track and Audio_Track (and maybe later Video_Track - * and MIDI_Track */ - -#include -#include "Track.H" - -#include "Transport.H" - -#include "../FL/Fl_Sometimes_Input.H" -#include "../FL/Fl_Sometimes_Pack.H" -#include -#include -#include -#include "FL/Fl_Scalepack.H" -#include "FL/Fl_Blink_Button.H" - -#include "Control_Sequence.H" -#include "Annotation_Sequence.H" - -#include "Track_Header.H" - -#include "const.h" -#include "debug.h" - -#include -#include "FL/menu_popup.H" - -extern char *instance_name; - - - -static Fl_Color -random_color ( void ) -{ - return fl_rgb_color( rand() % 255, rand() % 255, rand() % 255 ); -} - -static Fl_Menu_Button _menu( 0, 0, 0, 0, "Track" ); - - - -int Track::_soloing = 0; - -const char *Track::capture_format = "Wav 24"; -bool Track::colored_tracks = true; - - - -Track::Track ( const char *L, int channels ) : - Fl_Group ( 0, 0, 0, 0, 0 ) -{ - init(); - - if ( L ) - name( L ); - - color( random_color() ); - - configure_inputs( channels ); - configure_outputs( channels ); - - log_create(); -} - - -Track::Track ( ) : Fl_Group( 0, 0, 1, 1 ) -{ - init(); - - timeline->add_track( this ); -} - -Track::~Track ( ) -{ - Loggable::block_start(); - - /* must destroy sequences first to preserve proper log order */ - takes->clear(); - control->clear(); - annotation->clear(); - delete sequence(); - - takes = NULL; - control = NULL; - annotation = NULL; - - log_destroy(); - - /* ensure that soloing accounting is performed */ - solo( false ); - - timeline->remove_track( this ); - - /* give up our ports */ - configure_inputs( 0 ); - configure_outputs( 0 ); - - _sequence = NULL; - - if ( _name ) - free( _name ); - - Loggable::block_end(); -} - -void -Track::init ( void ) -{ - _capture_offset = 0; - _row = 0; - _sequence = NULL; - _name = NULL; - _selected = false; - _size = 1; - - record_ds = NULL; - playback_ds = NULL; - - labeltype( FL_NO_LABEL ); - -// clear_visible_focus(); - - Fl_Group::size( timeline->w(), height() ); - - Track *o = this; - o->box( FL_FLAT_BOX ); - - { - Track_Header *o = new Track_Header( x(), y(), w(), h() ); - - name_field = o->name_input; - record_button = o->rec_button; - mute_button = o->mute_button; - solo_button = o->solo_button; - menu_button = o->menu_button; - show_all_takes_button = o->show_all_takes_button; - overlay_controls_button = o->overlay_controls_button; - - name_field->callback( cb_button, this ); - record_button->callback( cb_button, this ); - mute_button->callback( cb_button, this ); - solo_button->callback( cb_button, this ); - - show_all_takes_button->callback( cb_button, this ); - overlay_controls_button->callback( cb_button, this ); - menu_button->callback( cb_button, this ); - - resizable( o ); -// o->color( (Fl_Color)53 ); - } - - { - /* this pack holds the active sequence, annotation sequence, control sequences and takes */ - Fl_Pack *o = pack = new Fl_Pack( x(), y(), w(), h() ); - o->type( Fl_Pack::VERTICAL ); - o->labeltype( FL_NO_LABEL ); - /* o->resize( x() + width(), y(), w() - width(), h() ); */ - - /* resizable( o ); */ - - { - Fl_Pack *o = annotation = new Fl_Pack( 0, 0, pack->w(), 1 ); - o->type( Fl_Pack::VERTICAL ); - o->end(); - } - - { - { - Fl_Group *o = controls_heading = new Fl_Group( 0, 0, pack->w(), 10 ); - o->box( FL_FLAT_BOX ); - o->color( fl_color_add_alpha( fl_rgb_color( 1,1,1 ), 127 ) ); - - { - Fl_Box *o = new Fl_Box( 0,0, Track::width(), 10 ); - o->label( "Controls" ); - o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - o->labelsize( 10 ); - } - - o->hide(); - o->end(); - o->resizable( 0 ); - } - - { - Fl_Sometimes_Pack *o = control = new Fl_Sometimes_Pack( 0, 0, pack->w(), 1 ); - o->spacing( 1 ); - o->box( FL_NO_BOX ); - o->color( FL_BACKGROUND_COLOR ); - o->type( Fl_Pack::VERTICAL ); - o->pack( true ); - o->hide(); - o->align( FL_ALIGN_TOP | FL_ALIGN_LEFT ); - o->end(); - } - } - - { - { - Fl_Group *o = takes_heading = new Fl_Group( 0, 0, pack->w(), 10 ); - o->box( FL_FLAT_BOX ); - o->color( fl_color_add_alpha( fl_rgb_color( 1,1,1 ), 127 ) ); - - { - Fl_Box *o = new Fl_Box( 0,0, Track::width(), 10 ); - o->label( "Takes" ); - o->align( FL_ALIGN_RIGHT | FL_ALIGN_INSIDE ); - o->labelsize( 10 ); - } - o->hide(); - o->end(); - o->resizable( 0 ); - } - - { - Fl_Pack *o = takes = new Fl_Pack( 0, 0, pack->w(), 1 ); - o->type( Fl_Pack::VERTICAL ); - o->end(); - o->hide(); - o->align( FL_ALIGN_TOP | FL_ALIGN_LEFT ); - } - } - - o->end(); - } - end(); -} - - - -void -Track::set ( Log_Entry &e ) -{ - for ( int i = 0; i < e.size(); ++i ) - { - const char *s, *v; - - e.get( i, &s, &v ); - - if ( ! strcmp( s, ":height" ) ) - { - size( atoi( v ) ); - adjust_size(); - } - else if ( ! strcmp( s, ":selected" ) ) - _selected = atoi( v ); -// else if ( ! strcmp( s, ":armed" - else if ( ! strcmp( s, ":name" ) ) - name( v ); - else if ( ! strcmp( s, ":inputs" ) ) - configure_inputs( atoi( v ) ); - else if ( ! strcmp( s, ":outputs" ) ) - configure_outputs( atoi( v ) ); - else if ( ! strcmp( s, ":color" ) ) - { - color( (Fl_Color)atoll( v ) ); - redraw(); - } - else if ( ! strcmp( s, ":show-all-takes" ) ) - show_all_takes( atoi( v ) ); - else if ( ! strcmp( s, ":overlay-controls" ) ) - overlay_controls( atoi( v ) ); - else if ( ! strcmp( s, ":solo" ) ) - solo( atoi( v ) ); - else if ( ! strcmp( s, ":mute" ) ) - mute( atoi( v ) ); - else if ( ! strcmp( s, ":arm" ) ) - armed( atoi( v ) ); - else if ( ! strcmp( s, ":sequence" ) ) - { - int i; - sscanf( v, "%X", &i ); - - if ( i ) - { - Audio_Sequence *t = (Audio_Sequence*)Loggable::find( i ); - - /* FIXME: our track might not have been - * defined yet... what should we do about this - * chicken/egg problem? */ - if ( t ) - { -// assert( t ); - - sequence( t ); - } - - } - - } - else if ( ! strcmp( s, ":row" ) ) - row( atoi( v ) ); - } -} - -void -Track::get ( Log_Entry &e ) const -{ - e.add( ":name", _name ); - e.add( ":sequence", sequence() ); - e.add( ":selected", _selected ); - e.add( ":color", (unsigned long)color()); -} - -void -Track::get_unjournaled ( Log_Entry &e ) const -{ - e.add( ":height", size() ); - e.add( ":inputs", input.size() ); - e.add( ":outputs", output.size() ); - e.add( ":show-all-takes", show_all_takes() ); - e.add( ":overlay-controls", overlay_controls() ); - e.add( ":armed", armed() ); - e.add( ":mute", mute() ); - e.add( ":solo", solo() ); - e.add( ":row", timeline->find_track( this ) ); -} - -int -Track::row ( void ) const -{ - return _row; -} - -void -Track::row ( int n ) -{ - _row = n; -} - -void -Track::log_children ( void ) const -{ - log_create(); - - for ( int i = 0; i < control->children(); i++ ) - ((Sequence*)control->child( i ))->log_children(); - - for ( int i = 0; i < annotation->children(); i++ ) - ((Sequence*)annotation->child( i ))->log_children(); - - for ( int i = takes->children(); i--; ) - ((Sequence*)takes->child( i ))->log_children(); - - sequence()->log_children(); -} - -void -Track::solo ( bool b ) -{ - if ( b && ! solo_button->value() ) - ++_soloing; - else if ( ! b && solo_button->value() ) - --_soloing; - - solo_button->value( b ); -} - - -void -Track::cb_button ( Fl_Widget *w, void *v ) -{ - ((Track*)v)->cb_button( w ); -} - -void -Track::cb_button ( Fl_Widget *w ) -{ - Logger log(this); - - if ( w == name_field ) - { - name( name_field->value() ); - } - else if ( w == record_button ) - { - - } - else if ( w == mute_button ) - { - - } - else if ( w == solo_button ) - { - if ( solo_button->value() ) - ++_soloing; - else - --_soloing; - } - else if ( w == show_all_takes_button ) - { - show_all_takes( show_all_takes_button->value() ); - } - else if ( w == overlay_controls_button ) - { - overlay_controls( overlay_controls_button->value() ); - } - else if ( w == menu_button ) - { - menu_popup( &menu(), menu_button->x(), menu_button->y() ); - } -} - -static int pack_visible( Fl_Pack *p ) -{ - int v = 0; - for ( int i = p->children(); i--; ) - if ( p->child( i )->visible() ) - v++; - - return v; -} - -/* adjust size of widget and children */ -void -Track::adjust_size ( void ) -{ - for ( int i = takes->children(); i--; ) - takes->child( i )->size( w(), height() ); - - for ( int i = annotation->children(); i--; ) - annotation->child( i )->size( w(), 24 ); - - for ( int i = control->children(); i--; ) - control->child( i )->size( w(), height() ); - - if ( overlay_controls() ) - { - for ( int i = 0; i < control->children(); i++ ) - { - Control_Sequence *o = (Control_Sequence*)control->child(i); - - if ( i != 0 ) - o->box( FL_NO_BOX ); - - o->header()->hide(); - } - - control->pack( false ); - } - else - { - for ( int i = 0; i < control->children(); i++ ) - { - Control_Sequence *o = (Control_Sequence*)control->child(i); - - o->box( FL_FLAT_BOX ); - - o->header()->show(); - } - - control->pack( true ); - } - - - int TY = 0; - - if ( annotation->children() ) - { - annotation->show(); - TY += 24 * pack_visible( annotation ); - } - else - annotation->hide(); - - /* height of the sequence */ - TY += height(); - - if ( control->children() ) - { - int TH; - - /* calculate height of control pack */ - if ( overlay_controls() ) - TH = height() * (control->children() ? 1 : 0); - else - TH = height() * pack_visible( control ); - - TY += TH; - - control->show(); - controls_heading->show(); - } - else - { - control->hide(); - controls_heading->hide(); - } - - if ( show_all_takes() ) - { - /* calculate height of takes pack */ - const int TH = height() * takes->children(); - - TY += TH; - - takes->show(); - takes_heading->show(); - } - else - { - takes_heading->hide(); - takes->hide(); - } - - if ( takes_heading->visible() ) - TY += takes_heading->h(); - if ( controls_heading->visible() ) - TY += controls_heading->h(); - - int TH; - - if ( ! size() ) - { - takes->hide(); - control->hide(); - TH = height(); - } - else - TH = TY; - - Fl_Group::size( w(), TH ); - - if ( sequence() ) - sequence()->size( w(), height() ); - - /* FIXME: why is this necessary? */ - if ( parent() ) - parent()->parent()->redraw(); -} - -void -Track::name ( const char *name ) -{ - if ( _name ) - free( _name ); - - _name = timeline->get_unique_track_name(name); - - if ( name_field ) - name_field->value( _name ); - - update_port_names(); -} - -const char * -Track::name ( void ) const -{ - return _name; -} - -void -Track::size ( int v ) -{ - if ( v < 0 || v > 4 ) - return; - - _size = v; - - adjust_size(); -} - - -void -Track::add ( Audio_Sequence * t ) -{ - t->track( this ); - - takes->insert( *t, 0 ); - - /* show the take header */ - t->child(0)->show(); - - t->color( fl_color_average( FL_BLACK, FL_GRAY, 0.25f ) ); - - t->labeltype( FL_ENGRAVED_LABEL ); -} - -void -Track::remove ( Audio_Sequence *t ) -{ - if ( ! takes ) - return; - - if ( sequence() == t ) - { - pack->remove( t ); - - if ( takes->children() ) - sequence( (Audio_Sequence*)takes->child( 0 ) ); - else - /* FIXME: should this ever happen? */ - _sequence = NULL; - } - else - takes->remove( t ); - -/* delete t; */ - - adjust_size(); -} - -void -Track::remove ( Annotation_Sequence *t ) -{ - if ( ! annotation ) - return; - - annotation->remove( t ); - - adjust_size(); -} - -void -Track::remove ( Control_Sequence *t ) -{ - if ( ! control ) - return; - - control->remove( t ); - - adjust_size(); -} - -void -Track::sequence ( Audio_Sequence * t ) -{ - if ( sequence() == t ) - { - DMESSAGE( "Attempt to set sequence twice" ); - return; - } - - t->track( this ); - - if ( sequence() ) - add( sequence() ); - - _sequence = t; - /* insert following the annotation pack */ - pack->insert( *t, 1 ); - - /* hide the take header */ - t->child(0)->hide(); - - t->color( FL_GRAY ); - t->labeltype( FL_NO_LABEL ); - - adjust_size(); -} - - -void -Track::add ( Control_Sequence *t ) -{ - DMESSAGE( "adding control sequence" ); - - t->track( this ); - - t->color( random_color() ); - -// control->insert( *t, 0 ); - control->add( t ); - - adjust_size(); -} - -void -Track::add ( Annotation_Sequence *t ) -{ - DMESSAGE( "adding annotation sequence" ); - - t->track( this ); - - annotation->add( t ); - - adjust_size(); -} - -/** add all widget on this track falling within the given rectangle to - the selection. */ -void -Track::select ( int X, int Y, int W, int H, - bool include_control, bool merge_control ) -{ - - Sequence *t = sequence(); - - X -= Track::width(); - - if ( ! ( t->y() > Y + H || t->y() + t->h() < Y ) ) - t->select_range( X, W ); - else - include_control = true; - - if ( include_control ) - for ( int i = control->children(); i--; ) - { - Control_Sequence *c = (Control_Sequence*)control->child( i ); - - if ( merge_control || - ( c->y() >= Y && c->y() + c->h() <= Y + H ) ) - c->select_range( X, W ); - } -} - - -void -Track::menu_cb ( Fl_Widget *w, void *v ) -{ - ((Track*)v)->menu_cb( (Fl_Menu_*) w ); -} - -void -Track::command_configure_channels ( int n ) -{ - /* due to locking this should only be invoked by direct user action */ - timeline->track_lock.wrlock(); - configure_inputs( n ); - configure_outputs( n ); - timeline->track_lock.unlock(); -} - -void -Track::menu_cb ( const Fl_Menu_ *m ) -{ - char picked[256]; - - m->item_pathname( picked, sizeof( picked ) ); - - DMESSAGE( "Picked: %s", picked ); - - Logger log( this ); - - if ( ! strcmp( picked, "Type/Mono" ) ) - { - command_configure_channels( 1 ); - } - else if ( ! strcmp( picked, "Type/Stereo" ) ) - { - command_configure_channels( 2 ); - } - else if ( ! strcmp( picked, "Type/Quad" ) ) - { - command_configure_channels( 4 ); - } - else if ( ! strcmp( picked, "Type/..." ) ) - { - const char *s = fl_input( "How many channels?", "3" ); - if ( s ) - { - - int c = atoi( s ); - - if ( c <= 0 || c > 10 ) - fl_alert( "Invalid number of channels." ); - else - { - command_configure_channels(c); - } - } - } - else if ( ! strcmp( picked, "/Add Control" ) ) - { - /* add audio track */ - char *name = get_unique_control_name( "Control" ); - - timeline->track_lock.wrlock(); - new Control_Sequence( this, name ); - timeline->track_lock.unlock(); - } - else if ( ! strcmp( picked, "/Overlay controls" ) ) - { - overlay_controls( ! m->mvalue()->value() ); - } - else if ( ! strcmp( picked, "/Add Annotation" ) ) - { - add( new Annotation_Sequence( this ) ); - } - else if ( ! strcmp( picked, "/Color" ) ) - { - unsigned char r, g, b; - - Fl::get_color( color(), r, g, b ); - - if ( fl_color_chooser( "Track Color", r, g, b ) ) - { - color( fl_rgb_color( r, g, b ) ); - } - - redraw(); - } - else if ( ! strcmp( picked, "Flags/Record" ) ) - { - armed( m->mvalue()->flags & FL_MENU_VALUE ); - } - else if ( ! strcmp( picked, "Flags/Mute" ) ) - { - mute( m->mvalue()->flags & FL_MENU_VALUE ); - } - else if ( ! strcmp( picked, "Flags/Solo" ) ) - { - solo( m->mvalue()->flags & FL_MENU_VALUE ); - } - else if ( ! strcmp( picked, "Size/Small" ) ) - { - size( 0 ); - } - else if ( ! strcmp( picked, "Size/Medium" ) ) - { - size( 1 ); - } - else if ( ! strcmp( picked, "Size/Large" ) ) - { - size( 2 ); - } - else if ( ! strcmp( picked, "Size/Huge" ) ) - { - size( 3 ); - } - else if ( ! strcmp( picked, "Size/Enormous" ) ) - { - size( 4 ); - } - else if ( ! strcmp( picked, "/Remove" ) ) - { - int r = fl_choice( "Are you certain you want to remove track \"%s\"?", "Cancel", NULL, "Remove", name() ); - - if ( r == 2 ) - { - timeline->command_remove_track( this ); - Fl::delete_widget( this ); - } - } - else if ( ! strcmp( picked, "/Rename" ) ) - { - ((Fl_Sometimes_Input*)name_field)->take_focus(); - } - else if ( ! strcmp( picked, "/Move Up" ) ) - { - timeline->command_move_track_up( this ); - } - else if ( ! strcmp( picked, "/Move Down" ) ) - { - timeline->command_move_track_down( this ); - } - else if ( !strcmp( picked, "Takes/Show all takes" ) ) - { - show_all_takes( ! m->mvalue()->value() ); - } - else if ( !strcmp( picked, "Takes/New" ) ) - { - timeline->track_lock.wrlock(); - sequence( (Audio_Sequence*)sequence()->clone_empty() ); - timeline->track_lock.unlock(); - } - else if ( !strcmp( picked, "Takes/Remove" ) ) - { - if ( takes->children() ) - { - Loggable::block_start(); - - timeline->track_lock.wrlock(); - - Audio_Sequence *s = sequence(); - - sequence( (Audio_Sequence*)takes->child( 0 ) ); - - delete s; - - timeline->track_lock.unlock(); - - Loggable::block_end(); - } - } - else if ( !strcmp( picked, "Takes/Remove others" )) - { - if ( takes->children() ) - { - Loggable::block_start(); - - takes->clear(); - - Loggable::block_end(); - } - } - else if ( !strncmp( picked, "Takes/", sizeof( "Takes/" ) - 1 ) ) - { - Audio_Sequence* s = (Audio_Sequence*)m->mvalue()->user_data(); - - timeline->track_lock.wrlock(); - sequence( s ); - timeline->track_lock.unlock(); - } -} - -/** retrun a pointer to the control sequence named /name/, or NULL if no control sequence is named /name/ */ -Control_Sequence * -Track::control_by_name ( const char *name ) -{ - for ( int i = control->children(); i-- ; ) - { - Control_Sequence *t = (Control_Sequence*)control->child( i ); - - if ( t->name() && name && ! strcmp( name, t->name() ) ) - return t; - } - - return NULL; -} - -/** return a malloc'd string representing a unique name for a new control sequence */ -char * -Track::get_unique_control_name ( const char *name ) -{ - char pat[256]; - - strcpy( pat, name ); - - for ( int i = 1; control_by_name( pat ); ++i ) - snprintf( pat, sizeof( pat ), "%s.%d", name, i ); - - return strdup( pat ); -} - - -/** build the context menu */ -Fl_Menu_Button & -Track::menu ( void ) const -{ - - int c = output.size(); - int s = size(); - - _menu.clear(); - - _menu.add( "Takes/Show all takes", 0, 0, 0, FL_MENU_TOGGLE | ( show_all_takes() ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Takes/New", 0, 0, 0 ); - - if ( takes->children() ) - { - _menu.add( "Takes/Remove", 0, 0, 0 ); - _menu.add( "Takes/Remove others", 0, 0, 0, FL_MENU_DIVIDER ); - - for ( int i = 0; i < takes->children(); ++i ) - { - Sequence *s = (Sequence *)takes->child( i ); - - char n[256]; - snprintf( n, sizeof(n), "Takes/%s", s->name() ); - - _menu.add( n, 0, 0, s); - } - } - - _menu.add( "Type/Mono", 0, 0, 0, FL_MENU_RADIO | ( c == 1 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Type/Stereo", 0, 0, 0, FL_MENU_RADIO | ( c == 2 ? FL_MENU_VALUE : 0 )); - _menu.add( "Type/Quad", 0, 0, 0, FL_MENU_RADIO | ( c == 4 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Type/...", 0, 0, 0, FL_MENU_RADIO | ( c == 3 || c > 4 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Overlay controls", 0, 0, 0, FL_MENU_TOGGLE | ( overlay_controls() ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Add Control", 0, 0, 0 ); - _menu.add( "Add Annotation", 0, 0, 0 ); - _menu.add( "Color", 0, 0, 0 ); - _menu.add( "Rename", FL_CTRL + 'n', 0, 0 ); - _menu.add( "Size/Small", FL_ALT + '1', 0, 0, FL_MENU_RADIO | ( s == 0 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Size/Medium", FL_ALT + '2', 0, 0, FL_MENU_RADIO | ( s == 1 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Size/Large", FL_ALT + '3', 0, 0, FL_MENU_RADIO | ( s == 2 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Size/Huge", FL_ALT + '4', 0, 0, FL_MENU_RADIO | ( s == 3 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Size/Enormous", FL_ALT + '5', 0, 0, FL_MENU_RADIO | ( s == 4 ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Flags/Record", FL_CTRL + 'r', 0, 0, FL_MENU_TOGGLE | ( armed() ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Flags/Mute", FL_CTRL + 'm', 0, 0, FL_MENU_TOGGLE | ( mute() ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Flags/Solo", FL_CTRL + 's', 0, 0, FL_MENU_TOGGLE | ( solo() ? FL_MENU_VALUE : 0 ) ); - _menu.add( "Move Up", FL_SHIFT + '1', 0, 0 ); - _menu.add( "Move Down", FL_SHIFT + '2', 0, 0 ); - _menu.add( "Remove", 0, 0, 0 ); // transport->rolling ? FL_MENU_INACTIVE : 0 ); - - _menu.callback( &Track::menu_cb, (void*)this ); - - return _menu; -} - -#include "FL/event_name.H" -#include "FL/test_press.H" - -static Fl_Widget *receptive_to_drop = NULL; - -void -Track::draw ( void ) -{ - fl_push_clip( x(), y(), w(), h() ); - - Fl_Color saved_color = color(); - - if ( ! Track::colored_tracks ) - color( FL_GRAY ); - - if ( _selected ) - { - Fl_Color c = color(); - - color( FL_RED ); - - Fl_Group::draw(); - - color( c ); - } - else - Fl_Group::draw(); - - if ( ((Track_Header*)child(0))->input_connector_handle == receptive_to_drop ) - { - Fl_Widget *o = ((Track_Header*)child(0))->input_connector_handle; - fl_draw_box( FL_OVAL_BOX, o->x(), o->y(), o->w(), o->h(), fl_color_add_alpha( FL_GREEN, 127 ) ); - } - - if ( ! Track::colored_tracks ) - color( saved_color ); - - fl_pop_clip(); -} - -int -Track::handle ( int m ) -{ - -/* if ( m != FL_NO_EVENT ) */ -/* DMESSAGE( "%s", event_name( m ) ); */ - static Fl_Widget *dragging = NULL; - - switch ( m ) - { - case FL_DND_ENTER: - case FL_DND_LEAVE: - case FL_DND_DRAG: - case FL_DND_RELEASE: - case FL_PASTE: - if ( Fl::event_x() > Track::width() ) - return sequence()->handle(m); - default: - break; - } - - switch ( m ) - { - case FL_KEYBOARD: - { - Fl_Menu_Button * men = &menu(); - - if ( Fl::event_key() == FL_Menu ) - { - menu_popup( men ); - return 1; - } - else - return men->test_shortcut() || Fl_Group::handle( m ); - } - case FL_MOUSEWHEEL: - { - Logger log( this ); - - if ( ! Fl::event_alt() ) - return Fl_Group::handle( m ); - - int d = Fl::event_dy(); - - if ( d < 0 ) - size( size() - 1 ); - else - size( size() + 1 ); - - return 1; - } - case FL_PUSH: - { - if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->color_box ) ) - { - dragging = this; - return 1; - } - if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ) - return 1; - - Logger log( this ); - - if ( Fl_Group::handle( m ) ) - return 1; - - if ( test_press( FL_BUTTON3 ) && Fl::event_x() < Track::width() ) - { - menu_popup( &menu() ); - return 1; - } - - return 0; - } - /* we have to prevent Fl_Group::handle() from getting these, otherwise it will mess up Fl::belowmouse() */ - case FL_ENTER: - case FL_LEAVE: - case FL_MOVE: - if ( Fl::event_x() >= Track::width() ) - { - return Fl_Group::handle(m); - } - return 1; - case FL_DND_ENTER: - return 1; - case FL_DND_LEAVE: - - if ( ! Fl::event_inside(this) && this == receptive_to_drop ) - { - receptive_to_drop = 0; - redraw(); - Fl::selection_owner(0); - } - return 1; - case FL_RELEASE: - if ( dragging == this ) - { - dragging = NULL; - timeline->insert_track( this, timeline->event_inside() ); - return 1; - } - return Fl_Group::handle( m ); - break; - case FL_DND_RELEASE: - receptive_to_drop = 0; - redraw(); - Fl::selection_owner(0); - return 1; - case FL_DND_DRAG: - { - - if ( receptive_to_drop == ((Track_Header*)child(0))->input_connector_handle ) - return 1; - - - - if ( Fl::event_inside( ((Track_Header*)child(0))->input_connector_handle ) - && receptive_to_drop != ((Track_Header*)child(0))->input_connector_handle ) - - { - receptive_to_drop = ((Track_Header*)child(0))->input_connector_handle; - redraw(); - return 1; - } - else - { - receptive_to_drop = NULL; - redraw(); - return 0; - } - } - case FL_PASTE: - { - receptive_to_drop = 0; - redraw(); - - if (! Fl::event_inside( ((Track_Header*)child(0))->input_connector_handle ) ) - return 0; - - /* NOW we get the text... */ - const char *text = Fl::event_text(); - - DMESSAGE( "Got drop text \"%s\"",text); - - if ( strncmp( text, "jack.port://", strlen( "jack.port://" ) ) ) - { - return 0; - } - - std::vector port_names; - - char *port_name; - int end; - while ( sscanf( text, "jack.port://%m[^\r\n]\r\n%n", &port_name, &end ) > 0 ) - { - DMESSAGE( "Scanning %s", port_name ); - port_names.push_back( port_name ); - free(port_name ); - - text += end; - } - - for ( unsigned int i = 0; i < input.size() && i < port_names.size(); i++) - { - const char *pn = port_names[i].c_str(); - - JACK::Port *ji = &input[i]; - - if ( ji->connected_to( pn ) ) - { - - DMESSAGE( "Disconnecting from \"%s\"", pn ); - ji->disconnect( pn ); - } - else - { - DMESSAGE( "Connecting to %s", pn ); - ji->connect( pn ); - } - } - - Fl::selection_owner(0); - - return 1; - } - case FL_DRAG: - { - if ( this != Fl::selection_owner() && - Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ) - { - char *s = (char*)malloc(256); - s[0] = 0; - - for ( unsigned int i = 0; i < output.size(); ++i ) - { - char *s2; - asprintf(&s2, "jack.port://%s:%s\r\n", instance_name, output[i].name() ); - - s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 ); - strcat( s, s2 ); - - free( s2 ); - } - - Fl::copy(s, strlen(s) + 1, 0); - Fl::selection_owner(this); - - free( s ); - - Fl::dnd(); - - return 1; - } - else - { - return 1; - } - } - default: - return Fl_Group::handle( m ); - } - - return 0; -} - -void -Track::connect_osc ( void ) -{ - for ( int j = control->children(); j--; ) - { - Control_Sequence *c = (Control_Sequence*)control->child( j ); - c->connect_osc(); - } -} - -void -Track::update_osc_connection_state ( void ) -{ - for ( int j = control->children(); j--; ) - { - Control_Sequence *c = (Control_Sequence*)control->child( j ); - c->update_osc_connection_state(); - } -} - -void -Track::process_osc ( void ) -{ - for ( int j = control->children(); j--; ) - { - Control_Sequence *c = (Control_Sequence*)control->child( j ); - c->process_osc(); - } -} diff --git a/timeline/src/Track.H b/timeline/src/Track.H deleted file mode 100644 index b2e0134..0000000 --- a/timeline/src/Track.H +++ /dev/null @@ -1,262 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include -#include "Sequence.H" -#include -#include -#include -#include -#include -#include -#include - -#include "Loggable.H" - -/* TODO: rename this to Audio_Track or something since it's clearly audio specific. */ - -#include -using std::vector; - -#include "JACK/Port.H" - -#include "Timeline.H" - -class Control_Sequence; -class Annotation_Sequence; -class Playback_DS; -class Record_DS; -// class JACK::Port; -class Audio_Region; -class Audio_File; -class Fl_Scalepack; -class Fl_Sometimes_Pack; -class Fl_Blink_Button; - -//class Audio_Sequence; - -#include "Audio_Sequence.H" - -class Track : public Fl_Group, public Loggable -{ - - /* not permitted */ - Track ( const Track &rhs ); - Track & operator= ( const Track &rhs ); - -public: - - Track ( const char *L, int channels=1 ); - virtual ~Track ( ); - - static bool soloing ( void ) { return _soloing; } - - static const char *capture_format; - - static bool colored_tracks; - - struct Capture - { - Audio_File *audio_file; - Audio_Region *region; - - Capture ( ) - { - region = 0; - audio_file = 0; - } - }; - - virtual Fl_Color color ( void ) const { return child(0)->color(); } - virtual void color ( Fl_Color c ) { child(0)->color( c ); } - - bool operator< ( const Track &rhs ) const - { - return _row < rhs._row; - } - -private: - - static int _soloing; - - char *_name; - - bool _selected; - - int _size; - - int _row; - - nframes_t _capture_offset; - - enum { AUDIO } _type; - - Audio_Sequence *_sequence; - - bool configure_outputs ( int n ); - bool configure_inputs ( int n ); - void command_configure_channels ( int n ); - - void update_port_names ( void ); - - Track ( ); - void init ( void ); - -protected: - - void get ( Log_Entry &e ) const; - void get_unjournaled ( Log_Entry &e ) const; - void set ( Log_Entry &e ); - - Fl_Scalepack *controls; - Fl_Sometimes_Pack *control; - Fl_Blink_Button *connected_indicator; - - Fl_Group *controls_heading; - Fl_Group *takes_heading; - -public: - - virtual void log_children ( void ) const; - - Fl_Input *name_field; - Fl_Button *record_button; - Fl_Button *mute_button; - Fl_Button *solo_button; - Fl_Button *show_all_takes_button; - Fl_Button *overlay_controls_button; - Fl_Button *menu_button; - - Fl_Pack *pack; - Fl_Pack *annotation; - Fl_Pack *takes; - - - vector input; /* input ports... */ - vector output; /* output ports... */ - - Playback_DS *playback_ds; - Record_DS *record_ds; - - /* for loggable */ - LOG_CREATE_FUNC( Track ); - - Control_Sequence * control_by_name ( const char *name ); - char * get_unique_control_name ( const char *name ); - - void add ( Annotation_Sequence *t ); - void remove ( Annotation_Sequence *t ); - - void add ( Control_Sequence *t ); - void add ( Audio_Sequence *t ); - void remove ( Audio_Sequence *t ); - void remove ( Control_Sequence *t ); - - void select ( int X, int Y, int W, int H, bool include_control, bool merge_control ); - - int size ( void ) const { return _size; } - - int ncontrols ( void ) { return ((Fl_Group*)control)->children(); } - - void adjust_size ( void ); - void size ( int v ); - - int height ( void ) const - { - static int table[] = { 25, 54, 80, 150, 300 }; - - return table[ _size ]; - } - - void show_all_takes ( bool b ) - { - show_all_takes_button->value( b ); - adjust_size(); - } - - bool show_all_takes ( void ) const - { - return show_all_takes_button->value(); - } - - void overlay_controls ( bool b ) - { - overlay_controls_button->value( b ); - adjust_size(); - } - bool overlay_controls ( void ) const - { - return overlay_controls_button->value(); - } - - void name ( const char *name ); - const char * name ( void ) const; - - bool mute ( void ) const { return mute_button->value(); } - void mute ( bool b ) { mute_button->value( b ); } - bool solo ( void ) const { return solo_button->value(); } - void solo ( bool b ); - - bool armed ( void ) const { return record_button->value(); } - void armed ( bool b ) { record_button->value( b ); } - - bool selected ( void ) const { return _selected; } - - int row ( void ) const; - void row ( int ); - - static void cb_button ( Fl_Widget *w, void *v ); - void cb_button ( Fl_Widget *w ); - - - static int width ( void ) { return 200; } - - void sequence ( Audio_Sequence * t ); - Audio_Sequence * sequence ( void ) const { return _sequence; } - - - Fl_Menu_Button & menu ( void ) const; - - static void menu_cb ( Fl_Widget *w, void *v ); - void menu_cb ( const Fl_Menu_ *m ); - - void draw ( void ); - int handle ( int m ); - - void process_osc ( void ); - void connect_osc ( void ); - void update_osc_connection_state ( void ); - - /* Engine */ - const Audio_Region *capture_region ( void ) const; - Capture *capture ( void ); - - void resize_buffers ( nframes_t nframes ); - nframes_t process_input ( nframes_t nframes ); - nframes_t process_output ( nframes_t nframes ); - void seek ( nframes_t frame ); - void undelay ( nframes_t frames ); - void compute_latency_compensation ( void ); - void record ( Capture *c, nframes_t frame ); - void write ( Capture *c, sample_t *buf, nframes_t nframes ); - void finalize ( Capture *c, nframes_t frame ); - -}; diff --git a/timeline/src/Track_Header.fl b/timeline/src/Track_Header.fl deleted file mode 100644 index f3821a0..0000000 --- a/timeline/src/Track_Header.fl +++ /dev/null @@ -1,154 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0300 -header_name {.h} -code_name {.cxx} -decl {\#include "FL/Fl_Sometimes_Input.H"} {public global -} - -decl {\#include "FL/Fl_Blink_Button.H"} {public global -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {Fl_PNG_Image *output_connector_image = NULL;} {private local -} - -decl {Fl_PNG_Image *input_connector_image = NULL;} {private local -} - -widget_class Track_Header {open - xywh {920 525 525 60} type Double box NO_BOX resizable visible -} { - Fl_Group box_group {open - private xywh {0 -1 200 67} box THIN_UP_BOX color 48 - code0 {o->resizable(0);} - } { - Fl_Group {} {open - xywh {0 -1 200 62} - code0 {o->resizable(0);} - } { - Fl_Input name_input { - label {input:} - xywh {15 2 140 22} labeltype NO_LABEL align 20 when 8 - class Fl_Sometimes_Input - } - Fl_Button track_inputs_indicator { - label in - tooltip {lit if inputs are connected} xywh {0 27 29 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide - } - Fl_Button track_outputs_indicator { - label out - tooltip {lit if outputs are connected} xywh {31 27 24 16} box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 labelcolor 53 hide - } - Fl_Button menu_button { - label menu - tooltip {Expand controls} xywh {15 26 31 24} selection_color 3 labelfont 4 labelsize 10 - } - Fl_Button overlay_controls_button { - label {c-} - tooltip {Expand controls} xywh {50 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 - } - Fl_Button show_all_takes_button { - label {t+} - tooltip {Show all takes} xywh {77 26 24 24} type Toggle selection_color 3 labelfont 5 labelsize 12 - } - Fl_Button rec_button { - label r - tooltip {arm for recording} xywh {118 26 24 24} type Toggle selection_color 88 labelfont 5 labelsize 12 - } - Fl_Button mute_button { - label m - tooltip mute xywh {145 26 24 24} type Toggle selection_color 63 labelfont 5 labelsize 12 - } - Fl_Button solo_button { - label s - tooltip solo xywh {172 26 24 24} type Toggle selection_color 91 labelfont 5 labelsize 12 - } - Fl_Box input_connector_handle { - tooltip {Drag and drop this input connector to make or break JACK connections} xywh {157 4 18 18} box FLAT_BOX - code0 {o->image( input_connector_image ? input_connector_image : input_connector_image = new Fl_PNG_Image( "input-connector", img_io_input_connector_10x10_png, img_io_input_connector_10x10_png_len ) );} - code1 {o->box(FL_NO_BOX);} - } - Fl_Box output_connector_handle { - tooltip {Drag and drop this output connector to make or break JACK connections} xywh {177 4 18 18} box FLAT_BOX - code0 {o->image( output_connector_image ? output_connector_image : output_connector_image = new Fl_PNG_Image( "output-connector", img_io_output_connector_10x10_png, img_io_output_connector_10x10_png_len ) );} - code1 {o->box(FL_NO_BOX);} - } - } - } - Fl_Box {} { - label {} - xywh {200 0 325 60} resizable - code0 {o->labeltype(FL_NO_LABEL);} - } - Fl_Box color_box {selected - xywh {0 0 10 60} box FLAT_BOX color 59 - } - Function {draw()} {open return_type {virtual void} - } { - code {color_box->color( color() ); - -Fl_Group::draw();} {} - } -} - -widget_class Control_Sequence_Header {open - xywh {333 978 200 55} type Double box NO_BOX visible -} { - Fl_Input name_input { - label {input:} - xywh {15 3 182 22} labeltype NO_LABEL align 20 when 8 textsize 12 - class Fl_Sometimes_Input - } - Fl_Button menu_button { - label menu - tooltip {Expand controls} xywh {15 26 31 24} selection_color 3 labelfont 4 labelsize 10 - } - Fl_Button outputs_indicator { - label out - tooltip {lit if outputs are connected} xywh {50 26 24 16} box BORDER_BOX down_box BORDER_BOX color 48 selection_color 90 labelfont 5 labelsize 10 - code0 {o->ignore_input( true );} - code1 {o->blink( false );} - class Fl_Blink_Button - } - Fl_Output osc_name_output { - xywh {60 26 92 24} color 32 labeltype NO_LABEL align 20 textsize 9 hide - } - Fl_Menu_Button osc_connect_menu {open - xywh {147 26 24 24} color 52 hide - } {} - Fl_Button delete_button { - label X - tooltip {Expand controls} xywh {172 26 24 24} labelfont 5 labelsize 12 - } -} - -widget_class Audio_Sequence_Header {open - xywh {418 762 200 50} type Double box NO_BOX resizable visible -} { - Fl_Group {} {open - xywh {0 0 200 55} - code0 {o->resizable(0);} - } { - Fl_Input name_input { - label {input:} - xywh {15 3 178 22} labeltype NO_LABEL align 20 when 8 textsize 12 - class Fl_Sometimes_Input - } - Fl_Button delete_button { - label X - tooltip {Expand controls} xywh {167 26 24 24} labelfont 5 labelsize 12 - } - Fl_Button promote_button { - label {@2} - tooltip {select this take as active sequence} xywh {142 26 24 24} labelfont 5 labelsize 12 - } - } -} diff --git a/timeline/src/Transport.C b/timeline/src/Transport.C deleted file mode 100644 index 27df7fd..0000000 --- a/timeline/src/Transport.C +++ /dev/null @@ -1,339 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* Controls the audio transport */ - -#include "Transport.H" -#include "Timeline.H" - -#include "Engine/Engine.H" - - - -Transport::Transport ( int X, int Y, int W, int H, const char *L ) - : Fl_Flowpack( X, Y, W, H, L ) -{ - recording = false; - rolling = false; - _stop_disables_record = true; - - bar = 0; - beat = 0; - tick = 0; - beats_per_minute = 120; - ticks_per_beat = 1920; - beat_type = 4; - beats_per_bar = 4; - next_time = 0; - frame_time =0; - frame_rate = 48000; - frame = 0; - - { _home_button = new Fl_Button(5, 5, 40, 44, "@|<"); - } // Fl_Button* _home_button - { _end_button = new Fl_Button(45, 5, 40, 44, "@>|"); - } // Fl_Button* _end_button - { _play_button = new Fl_Button(85, 5, 40, 44, "@>"); - } // Fl_Button* _play_button - { _record_button = new Fl_Button(130, 5, 40, 44, "@circle"); - } // Fl_Button* _record_button - { _punch_button = new Fl_Button(175, 5, 38, 21, "Punch"); - _punch_button->type(1); - _punch_button->labelsize(10); - } // Fl_Button* _punch_button - { _loop_button = new Fl_Button(175, 20, 38, 21, "Loop"); - _loop_button->type(1); - _loop_button->labelsize(10); - } // Fl_Button* _loop_button - { _new_take_button = new Fl_Button(225, 5, 60, 21, "New Take"); - _new_take_button->type(1); - _new_take_button->labelsize(10); - } // Fl_Button* _new_take_button - { _freewheel_button = new Fl_Button(225, 5, 60, 21, "Freewheel"); - _freewheel_button->type(1); - _freewheel_button->labelsize(10); - } // Fl_Button* _new_take_button - end(); - - Fl_Button *o; - - o = _home_button; - o->callback( cb_button, this ); - o->shortcut( FL_Home ); - - o = _end_button; - o->callback( cb_button, this ); - o->shortcut( FL_End ); - - o = _play_button; - o->callback( cb_button, this ); - o->shortcut( ' ' ); - - o = _record_button; - o->type( FL_TOGGLE_BUTTON ); - o->shortcut( 'R' ); - o->callback( cb_button, this ); - o->color2( FL_RED ); - o->when( FL_WHEN_CHANGED ); - - o = _punch_button; - o->type( FL_TOGGLE_BUTTON ); - o->shortcut( 'P' ); - o->callback( cb_button, this ); - o->when( FL_WHEN_CHANGED ); - o->color2( fl_color_average( FL_GRAY, FL_RED, 0.50 )); - o->tooltip( "Toggle punch in/out recording mode" ); - - o = _loop_button; - o->type( FL_TOGGLE_BUTTON ); - o->shortcut( 'L' ); - o->callback( cb_button, this ); - o->when( FL_WHEN_CHANGED ); - o->color2( fl_color_average( FL_GRAY, FL_GREEN, 0.50 )); - o->tooltip( "Toggle looped playback" ); - - o = _new_take_button; - o->type( FL_TOGGLE_BUTTON ); - o->shortcut( 'T' ); - o->callback( cb_button, this ); - o->when( FL_WHEN_CHANGED ); - o->color2( fl_color_average( FL_GRAY, FL_YELLOW, 0.50 ) ); - o->tooltip( "Toggle automatic creation of new takes for armed tracks" ); - - o = _freewheel_button; - o->type( FL_TOGGLE_BUTTON ); - o->shortcut( 'T' ); - o->callback( cb_button, this ); - o->when( FL_WHEN_CHANGED ); - o->color2( fl_color_average( FL_GRAY, FL_BLUE, 0.50 ) ); - o->tooltip( "When active, the next playback will be done in freewheeling mode" ); - - type( Fl_Pack::HORIZONTAL ); - flowdown( true ); - vspacing( 1 ); - hspacing( 1 ); - - dolayout(); -} - - - -void -Transport::cb_button ( Fl_Widget *w, void *v ) -{ - ((Transport*)v)->cb_button( w ); -} - -void -Transport::update_record_state ( void ) -{ - Fl_Button *w = _record_button; - - /* handle display */ - if ( w->value() ) - w->labelcolor( FL_BACKGROUND_COLOR ); - else - w->labelcolor( FL_FOREGROUND_COLOR ); - - w->redraw(); - - /* this covers the case where the record toggle button is - * pressed while the transport is already rolling. Recording - * should begin or end on the next frame */ - if ( rolling ) - { - if ( ! recording && w->value() ) - { - timeline->record(); - recording = true; - } - else if ( recording ) - { - timeline->stop(); - recording = false; - } - } -} - -/** cb_button - * common handler for all transport buttons */ -void -Transport::cb_button ( Fl_Widget *w ) -{ - if ( w == _home_button ) - locate( timeline->playback_home() ); - else if ( w == _end_button ) - locate( timeline->playback_end() ); - else if ( w == _play_button ) - toggle(); - else if ( w == _record_button ) - update_record_state(); - else if ( w == _punch_button ) - timeline->redraw(); -} - -void -Transport::toggle_record ( void ) -{ - _record_button->value( ! _record_button->value() ); - update_record_state(); -} - -bool -Transport::freewheel_enabled ( void ) const -{ - return _freewheel_button->value(); -} - -bool -Transport::rec_enabled ( void ) const -{ - return _record_button->value(); -} - -bool -Transport::punch_enabled ( void ) const -{ - return _punch_button->value(); -} - -bool -Transport::loop_enabled ( void ) const -{ - return _loop_button->value(); -} - -void -Transport::loop_enabled ( bool b ) -{ - _loop_button->value( b ); -} - -bool -Transport::automatically_create_takes ( void ) const -{ - return _new_take_button->value(); -} - -void -Transport::automatically_create_takes ( bool b ) -{ - _new_take_button->value( b ); -} - - - -int -Transport::handle ( int m ) -{ - /* FIXME: hack to avoid stealing focus */ - - if ( m == FL_FOCUS ) - return 0; - else - return Fl_Flowpack::handle( m ); -} - -/***********/ -/* Control */ -/***********/ - -void -Transport::poll ( void ) -{ - - jack_transport_state_t ts; - - ts = engine->transport_query( this ); - - rolling = ts == JackTransportRolling; -} - -void -Transport::locate ( nframes_t frame ) -{ - if ( ! engine ) - return; - - if ( ! recording ) - { - // don't allow seeking while record is in progress - engine->transport_locate( frame ); - - /* so there isn't a race waiting for the transport to sync */ - this->frame = frame; - } - - timeline->_created_new_takes = false; -} - - -void -Transport::start ( void ) -{ -// MESSAGE( "Starting transport" ); - if ( _record_button->value() ) - { - rolling = true; - update_record_state(); - } - - if ( engine ) - { - if ( _freewheel_button->value() ) - engine->freewheeling( true ); - - engine->transport_start(); - } -} - -void -Transport::stop ( void ) -{ -// MESSAGE( "Stopping transport" ); - if ( _record_button->value() ) - { - if ( _stop_disables_record ) - _record_button->value( 0 ); - - timeline->_created_new_takes = false; - - update_record_state(); - } - - if ( engine ) - { - engine->transport_stop(); - - if ( _freewheel_button->value() ) - { - engine->freewheeling( false ); - _freewheel_button->value( false ); - } - } -} - -void -Transport::toggle ( void ) -{ - if ( rolling ) - stop(); - else - start(); -} diff --git a/timeline/src/Transport.H b/timeline/src/Transport.H deleted file mode 100644 index 8323222..0000000 --- a/timeline/src/Transport.H +++ /dev/null @@ -1,86 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include -#include "types.h" - -#include -#include - -#include -#include - -class Transport : public jack_position_t, public Fl_Flowpack -{ - -private: - - bool _stop_disables_record; - - static void cb_button ( Fl_Widget *w, void *arg ); - void cb_button ( Fl_Widget *w ); - - /* not permitted */ - Transport ( const Transport &rhs ); - Transport & operator = ( const Transport &rhs ); - - Fl_Button *_home_button; - Fl_Button *_end_button; - Fl_Button *_play_button; - Fl_Button *_record_button; - Fl_Button *_punch_button; - Fl_Button *_loop_button; - Fl_Button *_new_take_button; - Fl_Button *_freewheel_button; - - void update_record_state ( void ); - -public: - - Transport ( int X, int Y, int W, int H, const char *L=0 ); - - bool freewheel_enabled ( void ) const; - bool rec_enabled ( void ) const; - bool punch_enabled ( void ) const; - bool loop_enabled ( void ) const; - void loop_enabled ( bool b ); - - void automatically_create_takes ( bool b ); - bool automatically_create_takes ( void ) const; - - void stop_disables_record ( bool b ) { _stop_disables_record = b; } - bool stop_disables_record ( void ) const { return _stop_disables_record; } - - void toggle_record ( void ); - int handle ( int m ); - - volatile bool rolling; - volatile bool recording; - - void poll ( void ); - void locate ( nframes_t frame ); - void start ( void ); - void stop ( void ); - void toggle ( void ); -}; - -extern Transport* transport; diff --git a/timeline/src/Waveform.C b/timeline/src/Waveform.C deleted file mode 100644 index a6bb8b9..0000000 --- a/timeline/src/Waveform.C +++ /dev/null @@ -1,143 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -/* routines to draw a waveform from peak data */ - -#include -#include -#include "Waveform.H" - -#include -#include -using std::min; -using std::max; -#include - - - -bool Waveform::fill = true; -bool Waveform::outline = true; -bool Waveform::vary_color = true; -bool Waveform::logarithmic = true; - - - -/* TODO: split the variations into separate functions. eg, plain, - * outlined, filled, polygonal, rectified. */ - -void -Waveform::scale ( Peak *pbuf, int npeaks, float gain ) -{ - /* scale it */ - for ( int j = npeaks; j--; ) - { - pbuf[ j ].min *= gain; - pbuf[ j ].max *= gain; - } -} - -/** draw a portion of /clip/'s waveform. coordinates are the portion to draw */ -void -Waveform::draw ( int X, int Y, int W, int H, - const Peak *pbuf, int peaks, int skip, - Fl_Color fg_color, Fl_Color bg_color ) -{ - int j; - - int start = 0; - - const int halfheight = H / 2; - const int mid = Y + halfheight; - const int ty = Y + halfheight; - - W = min( peaks, W ); - - if ( ! W ) - return; - - fg_color = fl_color_add_alpha( Fl::get_color( fg_color ), 200 ); - - if ( Waveform::fill ) - { - if ( Waveform::vary_color ) - { - j = start; - for ( int x = X; x < X + W; ++x, j += skip ) - { - const Peak p = pbuf[ j ]; - - const float diff = fabs( p.max - p.min ); - - if ( diff > 2.0f ) - fl_color( FL_RED ); - else - fl_color( fl_color_average( fg_color, bg_color, diff * 0.5f ) ); - - const int ty = mid - ( halfheight * p.min ); - const int by = mid - ( halfheight * p.max ); - fl_line( x, ty, x, by ); - } - } - else - { - fl_color( fg_color ); - - fl_begin_complex_polygon(); - - j = start; - - for ( int x = X; x <= X + W; x++, j += skip ) - fl_vertex( x, ty - ( halfheight * pbuf[ j ].min ) ); - - j -= skip; - - for ( int x = X + W; x >= X; x--, j -= skip ) - fl_vertex( x, ty - ( halfheight * pbuf[ j ].max ) ); - - fl_end_complex_polygon(); - } - } - - if ( Waveform::outline ) - { - fl_color( bg_color ); - - fl_line_style( FL_SOLID, 0 ); - - fl_begin_line(); - - j = start; - - for ( int x = X; x < X + W; x++, j += skip ) - fl_vertex( x, ty - ( halfheight * pbuf[ j ].min ) ); - - fl_end_line(); - - fl_begin_line(); - - j = start; - - for ( int x = X; x < X + W; x++, j += skip ) - fl_vertex( x, ty - ( halfheight * pbuf[ j ].max ) ); - - fl_end_line(); - - fl_line_style( FL_SOLID, 0 ); - } -} diff --git a/timeline/src/Waveform.H b/timeline/src/Waveform.H deleted file mode 100644 index eed7747..0000000 --- a/timeline/src/Waveform.H +++ /dev/null @@ -1,39 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - - -#pragma once - -#include "Engine/Peak.H" - -class Waveform { - -public: - - static bool fill; - static bool outline; - static bool vary_color; - static bool logarithmic; - - static void scale ( Peak *pbuf, int npeaks, float gain ); - static void draw ( int X, int Y, int W, int H, - const Peak *pbuf, int peaks, int skip, - Fl_Color fg_color, Fl_Color bg_color ); - -}; diff --git a/timeline/src/const.h b/timeline/src/const.h deleted file mode 100644 index 385b0ce..0000000 --- a/timeline/src/const.h +++ /dev/null @@ -1,22 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -extern const char *APP_NAME; -extern const char *APP_TITLE; -#define __MODULE__ "non-timeline" diff --git a/timeline/src/main.C b/timeline/src/main.C deleted file mode 100644 index a341240..0000000 --- a/timeline/src/main.C +++ /dev/null @@ -1,292 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#include - - -#include -#include -#include -#include -#include -#include -#include - -/* for registrations */ -#include "Audio_Region.H" -#include "Sequence.H" -#include "Audio_Sequence.H" -#include "Timeline.H" -#include "Tempo_Sequence.H" -#include "Time_Sequence.H" -#include "Annotation_Sequence.H" -#include "Control_Sequence.H" -#include "Cursor_Sequence.H" -#include "Track.H" - -#include "TLE.H" -#include "Timeline.H" - -#include "Project.H" -#include "Transport.H" -#include "Engine/Engine.H" - -#include "Thread.H" - -#include - -extern void set_nsm_callbacks ( nsm_client_t *nsm ); - -Engine *engine; -Timeline *timeline; -Transport *transport; -TLE *tle; -nsm_client_t *nsm; - -char *instance_name = NULL; - -/* TODO: put these in a header */ -#define USER_CONFIG_DIR ".non-daw/" - -const char *APP_NAME = "Non-Timeline"; -const char *APP_TITLE = "The Non-Timeline"; - -const char COPYRIGHT[] = "Copyright (C) 2008-2013 Jonathan Moore Liles"; - -const double NSM_CHECK_INTERVAL = 0.25f; - -#define PACKAGE "non" - -#include "const.h" -#include "debug.h" - -char *user_config_dir; - -#include - -static int -ensure_dirs ( void ) -{ - asprintf( &user_config_dir, "%s/%s", getenv( "HOME" ), USER_CONFIG_DIR ); - - int r = mkdir( user_config_dir, 0777 ); - - return r == 0 || errno == EEXIST; -} - -#include - -#include - -void -shift ( char **argv, int *argc, int n ) -{ - int i; - - for ( i = 0; i < *argc; ++i ) - argv[ i ] = argv[ i + n ]; - - argv[ i ] = 0; - argc -= n; -} - -extern Timeline *timeline; - -void -check_nsm ( void * v ) -{ - nsm_check_nowait( nsm ); - Fl::repeat_timeout( NSM_CHECK_INTERVAL, check_nsm, v ); -} - -static int got_sigterm = 0; - -void -sigterm_handler ( int ) -{ - got_sigterm = 1; - Fl::awake(); -} - -void -check_sigterm ( void * ) -{ - if ( got_sigterm ) - { - MESSAGE( "Got SIGTERM, quitting..." ); - timeline->command_quit(); - } -} - -int -main ( int argc, char **argv ) -{ - if ( !strcmp( argv[0], "non-daw" ) ) - { - /* use old app name and title */ - APP_NAME = "Non-DAW"; - APP_TITLE = "The Non-DAW"; - } - - printf( "%s %s -- %s\n", APP_TITLE, VERSION, COPYRIGHT ); - - if ( ! Fl::visual( FL_DOUBLE | FL_RGB ) ) - { - WARNING( "Xdbe not supported, FLTK will fake double buffering." ); - } - - - Thread::init(); - - Thread thread( "UI" ); - thread.set(); - - signal( SIGTERM, sigterm_handler ); - signal( SIGHUP, sigterm_handler ); - signal( SIGINT, sigterm_handler ); - - fl_register_images(); - - /* welcome to C++ */ - LOG_REGISTER_CREATE( Annotation_Point ); - LOG_REGISTER_CREATE( Annotation_Region ); - LOG_REGISTER_CREATE( Annotation_Sequence ); - LOG_REGISTER_CREATE( Audio_Region ); - LOG_REGISTER_CREATE( Audio_Sequence ); - LOG_REGISTER_CREATE( Control_Point ); - LOG_REGISTER_CREATE( Control_Sequence ); - LOG_REGISTER_CREATE( Tempo_Point ); - LOG_REGISTER_CREATE( Time_Point ); - LOG_REGISTER_CREATE( Cursor_Point ); - LOG_REGISTER_CREATE( Cursor_Region ); - LOG_REGISTER_CREATE( Track ); - - signal( SIGPIPE, SIG_IGN ); - - if ( ! ensure_dirs() ) - FATAL( "Cannot create required directories" ); - - instance_name = strdup( APP_NAME ); - bool instance_override = false; - - - const char *osc_port = NULL; - - static struct option long_options[] = - { - { "help", no_argument, 0, '?' }, - { "instance", required_argument, 0, 'i' }, - { "osc-port", required_argument, 0, 'p' }, - { 0, 0, 0, 0 } - }; - - int option_index = 0; - int c = 0; - - while ( ( c = getopt_long_only( argc, argv, "", long_options, &option_index ) ) != -1 ) - { - switch ( c ) - { - - case 'p': - DMESSAGE( "Using OSC port %s", optarg ); - osc_port = optarg; - break; - case 'i': - DMESSAGE( "Using instance name %s", optarg ); - free( instance_name ); - instance_name = strdup( optarg ); - instance_override = true; - break; - case '?': - printf( "\nUsage: %s [--instance instance_name] [--osc-port portnum] [path_to_project]\n\n", argv[0] ); - exit(0); - break; - } - } - - /* we don't really need a pointer for this */ - // will be created on project new/open - engine = NULL; - - tle = new TLE; - - nsm = nsm_new(); - set_nsm_callbacks( nsm ); - - MESSAGE( "Starting GUI" ); - - tle->run(); - - timeline->init_osc( osc_port ); - - tle->main_window->show( 0, NULL ); - - char *nsm_url = getenv( "NSM_URL" ); - - if ( nsm_url ) - { - if ( ! nsm_init( nsm, nsm_url ) ) - { - if ( instance_override ) - WARNING( "--instance option is not available when running under session management, ignoring." ); - - if ( optind < argc ) - WARNING( "Loading files from the command-line is incompatible with session management, ignoring." ); - - nsm_send_announce( nsm, APP_NAME, ":progress:switch:", argv[0] ); - - /* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */ - Fl::add_timeout( NSM_CHECK_INTERVAL, check_nsm, NULL ); - } - } - else - { - if ( optind < argc ) - { - MESSAGE( "Loading \"%s\"", argv[optind] ); - Fl::lock(); - tle->open( argv[optind] ); - Fl::unlock(); - } - } - - Fl::add_check( check_sigterm ); - - Fl::run(); - - /* cleanup for valgrind's sake */ - - delete timeline; - timeline = NULL; - - delete tle; - tle = NULL; - - if ( engine ) - { - delete engine; - engine = NULL; - } - - nsm_free( nsm ); - nsm = NULL; - - MESSAGE( "Your fun is over" ); -} diff --git a/timeline/src/types.h b/timeline/src/types.h deleted file mode 100644 index cd3cc2c..0000000 --- a/timeline/src/types.h +++ /dev/null @@ -1,25 +0,0 @@ - -/*******************************************************************************/ -/* Copyright (C) 2008 Jonathan Moore Liles */ -/* */ -/* This program is free software; you can redistribute it and/or modify it */ -/* under the terms of the GNU General Public License as published by the */ -/* Free Software Foundation; either version 2 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ -/* more details. */ -/* */ -/* You should have received a copy of the GNU General Public License along */ -/* with This program; see the file COPYING. If not,write to the Free Software */ -/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*******************************************************************************/ - -#pragma once - -#include - -typedef jack_nframes_t nframes_t; -typedef float sample_t; diff --git a/timeline/wscript b/timeline/wscript deleted file mode 100644 index 2a46a59..0000000 --- a/timeline/wscript +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python -import subprocess -import waflib.Options as Options -import string -import os; - -# Version of this package (even if built as a child) -PACKAGE_VERSION = '1.2.0' - -# Variables for 'waf dist' -APPNAME = 'non-timeline' -VERSION = PACKAGE_VERSION - -# Mandatory variables -top = '.' -out = 'build' - -def options(opt): - opt.load('compiler_c') - opt.load('compiler_cxx') - opt.load('gnu_dirs') - -def configure(conf): - conf.load('compiler_c') - conf.load('compiler_cxx') - conf.load('gnu_dirs') - - # conf.env.append_value('CFLAGS', '-D_LARGEFILE64_SOURCE') - # conf.env.append_value('CFLAGS', '-D_FILE_OFFSET_BITS=64') - # conf.env.append_value('CXXFLAGS', '-D_LARGEFILE64_SOURCE') - # conf.env.append_value('CXXFLAGS', '-D_FILE_OFFSET_BITS=64') - - conf.check_cfg(package='sndfile', uselib_store='SNDFILE',args="--cflags --libs", - atleast_version='1.0.18', mandatory=True) - - conf.check(msg='Checking for SF_FORMAT_VORBIS', - define_name='HAVE_SF_FORMAT_VORBIS', - fragment='#include \nint main ( int argc, char **argv ) { return SF_FORMAT_VORBIS; }', - execute=False, mandatory=False) - - conf.define('VERSION', PACKAGE_VERSION) - conf.define('SYSTEM_PATH', '/'.join( [ conf.env.DATADIR, APPNAME ] ) ) - conf.define('DOCUMENT_PATH', '/'.join( [ conf.env.DATADIR, 'doc' ] ) ) - conf.define('PIXMAP_PATH', '/'.join( [ conf.env.DATADIR, 'pixmaps' ] ) ) - - conf.write_config_header('config.h', remove=False) - - print('') - -def build(bld): - # libs = 'LILV SUIL JACK SERD SRATOM LV2' - - libs = '' - - obj = bld(features = 'cxx cxxprogram', - source = ''' -src/Annotation_Region.C -src/Audio_Region.C -src/Audio_Sequence.C -src/Control_Point.C -src/Control_Sequence.C -src/Cursor_Point.C -src/Cursor_Region.C -src/Cursor_Sequence.C -src/Engine/Audio_File.C -src/Engine/Audio_File_Dummy.C -src/Engine/Audio_File_SF.C -src/Engine/Audio_Region.C -src/Engine/Audio_Sequence.C -src/Engine/Control_Sequence.C -src/Engine/Disk_Stream.C -src/Engine/Engine.C -src/Engine/Peaks.C -src/Engine/Playback_DS.C -src/Engine/Record_DS.C -src/Engine/Timeline.C -src/Engine/Track.C -src/NSM.C -src/OSC_Thread.C -src/Project.C -src/Sequence.C -src/Sequence_Point.C -src/Sequence_Region.C -src/Sequence_Widget.C -src/TLE.fl -src/Track_Header.fl -src/Tempo_Point.C -src/Tempo_Sequence.C -src/Time_Point.C -src/Time_Sequence.C -src/Timeline.C -src/Track.C -src/Transport.C -src/Waveform.C -src/main.C -''', - target = 'non-timeline', - includes = ['.', 'src', '..', '../nonlib'], - uselib = [ 'JACK', 'LIBLO', 'SNDFILE', 'NTK', 'NTK_IMAGES', 'PTHREAD'], - use = [ 'fl_widgets', 'nonlib'], - install_path = '${BINDIR}') - - obj = bld(features = 'cxx cxxprogram', - source='bin/import-ardour-session_gui.fl', - target = 'import-ardour-session_gui', - includes = ['.', 'src', '..', '../nonlib'], - uselib = [ 'NTK', 'NTK_IMAGES', 'PTHREAD'], - ## use = [ 'fl_widgets', 'nonlib'], - install_path = '${BINDIR}') - - bld.install_files('${BINDIR}', 'bin/import-ardour-session', chmod=0o0555, - relative_trick=True) - - bld( features = 'subst', - source = 'non-timeline.desktop.in', - target = 'non-timeline.desktop', - encoding = 'utf8', - install_path = "${DATADIR}" + '/applications', - BIN_PATH = bld.env.BINDIR ) - - - bld.symlink_as( '${BINDIR}/' + 'non-daw', APPNAME ) - - start_dir = bld.path.find_dir( 'icons/hicolor' ) - - bld.install_files('${DATADIR}/icons/hicolor', start_dir.ant_glob('**/*.png'), - cwd=start_dir, relative_trick=True) - - bld.install_as('${DATADIR}/pixmaps/' + APPNAME + '/icon-256x256.png', 'icons/hicolor/256x256/apps/' + APPNAME + '.png') - - bld.install_files( '/'.join( [ '${DATADIR}/doc', APPNAME ] ), bld.path.ant_glob( 'doc/*.html doc/*.png' ) ) - diff --git a/tools.waf/ntk_fluid.py b/tools.waf/ntk_fluid.py deleted file mode 100644 index d8389b4..0000000 --- a/tools.waf/ntk_fluid.py +++ /dev/null @@ -1,18 +0,0 @@ -from waflib import Task -from waflib.TaskGen import extension - -class ntk_fluid(Task.Task): - color = 'BLUE' - ext_out = ['.h'] - run_str = '${NTK_FLUID} -c -o ${TGT[0].abspath()} -h ${TGT[1].abspath()} ${SRC}' - -@extension('.fl') -def fluid(self, node): - """add the .fl to the source list; the cxx file generated will be compiled when possible""" - cpp = node.change_ext('.C') - hpp = node.change_ext('.H') - self.create_task('ntk_fluid', node, [cpp, hpp]) - - if 'cxx' in self.features: - self.source.append(cpp) - diff --git a/wscript b/wscript index 647fafd..b5112f8 100644 --- a/wscript +++ b/wscript @@ -30,8 +30,7 @@ def options(opt): def configure(conf): conf.load('compiler_c') conf.load('compiler_cxx') - conf.load('gnu_dirs') - conf.load('ntk_fluid',tooldir='tools.waf') + conf.load('gnu_dirs') conf.load('gccdeps') conf.line_just = 52